Linux 和 Windows 下实现多进程的方式以及管道操作

一、多进程

1.windows 多进程

使用 #include<windows.h> 下面的

1 BOOL  CreateProcess( 
2         LPCWSTR pszImageName,  LPCWSTR pszCmdLine, 
3         LPSECURITY_ATTRIBUTES psaProcess, 
4         LPSECURITY_ATTRIBUTES psaThread, 
5         BOOL fInheritHandles,  DWORD fdwCreate, 
6         LPVOID pvEnvironment,  LPWSTR pszCurDir, 
7         LPSTARTUPINFOW psiStartInfo, 
8         LPPROCESS_INFORMATION pProcInfo 
9 );
View Code

其中几个关键的形参为:

    参数pszImageName   //指向一个NULL终止的字符串,用来指定可执行程序的名字。
    e.g:
1 STARTUPINFO sui;
2 PROCESS_INFORMATION pi;
3 ZeroMemory(&sui,sizeof(STARTUPINFO));
4 sui.cb = sizeof(STARTUPINFO);
5 sui.dwFlags = STARTF_USESTDHANDLES;
6 sui.hStdInput = hRead;
7 sui.hStdOutput = hWrite;
8 sui.hStdError = GetStdHandle(STD_ERROR_HANDLE);
9         CreateProcess("../.../run/Chilid.exe",NULL,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi);
View Code

      参数pszCmdLine    //用来指定传递给新进程的命令行字符串

    e.g:
1  TCHAR szApp[MAX_PATH] = TEXT("netstat -s");
2           CreateProcess(NULL,szApp,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi);
View Code
     参数psiStartInfo   //指向一个 StartUpInfo 的结构体的指针,用来指定新进程的主窗口如何显示
 1 typedef struct _STARTUPINFOA {
 2     DWORD cb;
 3     LPSTR lpReserved;
 4     LPSTR lpDesktop;
 5     LPSTR lpTitle;
 6     DWORD dwX;
 7     DWORD dwY;
 8     DWORD dwXSize;
 9     DWORD dwYSize;
10     DWORD dwXCountChars;
11     DWORD dwYCountChars;
12     DWORD dwFillAttribute;
13     DWORD dwFlags;
14     WORD wShowWindow;
15     WORD cbReserved2;
16     LPBYTE lpReserved2;
17     HANDLE hStdInput;
18     HANDLE hStdOutput;
19     HANDLE hStdError;
20 } STARTUPINFOA, *LPSTARTUPINFOA;
View Code

      对于 dwFlags 参数来说,如果其设置为 STARTF_USESTDHANDLES ,则将会使用该 STARTUPINFO 结构体中的     hStdInput , hStdOutput , hStdError 成员,来设置新创       建的进程的标准输入,标准输出,标准错误句柄。

      参数 pProcInfo    //为一个输出参数,指向一个 PROCESS_INFORMATION 结构体的指针,用来接收关于新进程的标识信息。

      其中 hProcess 和 hThread 分别用来标识新创建的进程句柄和新创建的进程的主线程句柄。

      dwProcessId 和 dwThreadId 分别是全局进程标识符和全局线程标识符。前者可以用来标识一个进程,后者用来标识一个线程

1 typedef struct _PROCESS_INFORMATION 
2 {   HANDLE hProcess;             
3     HANDLE hThread;             
4     DWORD dwProcessId;              
5     DWORD dwThreadId; 
6 }PROCESS_INFORMATION;
View Code

【注】CreateProcess()和CreateThread()的区别,是前者创建的是进程,而后者创建的是线程。

2. Linux下多进程
    Linux创建线程的主要方式有:
    <unistd.h> ---- fork();

    <unistd.h> ---- exec系列;

    <stdlib.h> ---- sysytem();

     e.g

     system("cd /home/root/");

   【注】linux下创建线程的方式

    <pthread.h> ---- pthread_create

    e.g: 

    int * thread(void *arg){}

    pthread_t id;   //记录创建线程的id

    pthread_create(&id,NULL,(void*) thread,NULL);

二、管道

1、windows 下的管道

     a. 匿名管道 -- 进程和其子进程之间通信

 1 #include<iostream>
 2 #include <windows.h>
 3 #define MAX_PATH 1024
 4 using namespace std;
 5 int main(){
 6 TCHAR szApp[MAX_PATH] = TEXT("netstat -s");
 7  char ReadBuf[100];
 8  DWORD ReadNum;
 9  HANDLE hRead = NULL; // 管道读句柄
10  HANDLE hWrite = NULL; // 管道写句柄
11     SECURITY_ATTRIBUTES sa = {0};
12     sa.nLength = sizeof(sa);  
13     sa.lpSecurityDescriptor = NULL;  
14     sa.bInheritHandle = TRUE;  
15     bool bRet = CreatePipe(&hRead, &hWrite, &sa, 0);
16     if (bRet)
17     {
18      cout<<"创建管道成功"<<endl;
19     }
20     else{
21      cout<<"创建管道失败"<<endl;
22     }
23     STARTUPINFO si = {sizeof(si)};  
24     PROCESS_INFORMATION pi = {0};  
25     si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;    
26     si.hStdOutput = hWrite;  
27     si.hStdError = hWrite;  
28     si.wShowWindow = SW_HIDE;  
29     HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);
30     GetStartupInfo(&si);
31     bRet = CreateProcess(NULL,szApp,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi);  //创建一个执行命令行的进程
32     CloseHandle(pi.hThread);  
33     CloseHandle(pi.hProcess);  
34     CloseHandle(hWrite);  
35     int i = 0;
36     while(ReadFile(hRead,ReadBuf,1024,&ReadNum,NULL)){       //对管道进行读操作           
37      ReadBuf[ReadNum] = '\0';
38         cout<<"panfei"<<endl;
39         cout<<i++<<endl;
40      //cout<<ReadBuf<<endl;
41     }
42     if(GetLastError() == ERROR_BROKEN_PIPE)
43      cout<<"管道被子进程关闭"<<endl;
44     ExitProcess(0);
45  return 0;
46 }
View Code

     b. 命名管道 -- 可以实现两个无任何亲缘关系的进程之间的数据传递

       server端:

 1 #include <iostream>
 2         #inserclude <Windows.h>
 3         HANDLE hpipe = INVALID_HANDLE_VALUE;
 4         LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");    //★管道的名称必须这样命名,托付给系统管理
 5         int main(){
 6  SECURITY_ATTRIBUTES sa;
 7  sa.bInheritHandle = TRUE;
 8  sa.lpSecurityDescriptor = NULL;
 9  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
10  hpipe = CreateNamedPipe(                                                //创建命名pipe
11   lpszPipename,             // pipe name
12   PIPE_ACCESS_DUPLEX,       // read/write access
13   PIPE_TYPE_MESSAGE |       // message type pipe
14   PIPE_READMODE_MESSAGE |   // message-read mode
15   PIPE_WAIT,                // blocking mode
16   PIPE_UNLIMITED_INSTANCES, // max. instances  
17   BUFSIZ,                   // output buffer size
18   BUFSIZ,                   // input buffer size
19   0,                        // client time-out
20   NULL);                    // default security attribute
21  if (hpipe == INVALID_HANDLE_VALUE)
22  {
23   cout<<"CreateNamedPipe failed, GLE=%d.\n"<<endl;;
24   return -1;
25  }
26  BOOL fConnected = ConnectNamedPipe(hpipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);   //等待有其他进程连接该pipe ,一旦有进程连接该pipe,下面的代码才会执行
27  char buf[1024] = {'a','b','a','\0'};
28  WriteFile(hpipe,buf,3,NULL,NULL);
29  return 0;
30 }
View Code

 client端:

 1  int main(){
 2              hPipe = CreateFile(             //连接server创建的pipe
 3                       lpszPipename,   // pipe name
 4                       GENERIC_READ |  // read and write access
 5                       GENERIC_WRITE,
 6                       0,              // no sharing
 7                       NULL,           // default security attributes
 8                       OPEN_EXISTING,  // opens existing pipe
 9                       0,              // default attributes
10                       NULL);          // no template file 
11               DWORD dwMode = PIPE_READMODE_MESSAGE;
12               BOOL fSuccess = SetNamedPipeHandleState(            //设置管道的状态,设置到读取状态
13               hPipe,    // pipe handle
14               &dwMode,  // new pipe mode
15               NULL,     // don't set maximum bytes
16                                     NULL);    // don't set maximum time
17               DWORD cbRead;
18               fSuccess = ReadFile(                                        //读取管道中的数据
19               hPipe,    // pipe handle
20               readBuf,    // buffer to receive reply
21               BUFSIZ*sizeof(TCHAR),  // size of buffer
22               &cbRead,  // number of bytes read
23                NULL);    // not overlapped
24               cout<<readBuf<<endl;
25         }
View Code

2.  Linux 下的管道

     a. 匿名管道  

      e.g

 1  #include<stdio.h>
 2            #include<stdlib.h>
 3            #include<unistd.h>
 4            int main(){
 5                 int pfd[2];                  //用于保存打开管道后的两个文件描述符号
 6                 pid_t cpid;                 //进程id
 7                 char buf;
 8                 if(pipe(pfd) == -1){
 9                       fprintf("Pipe created fail!");
10                 }
11                 cpid = fork();
12                 if(cpid == 0){
13                        close(pfd[1]);       //读管道前关闭管道写端
14                        while(read(pfd[0],&buf,1){     //读取管道
15                             printf("%s\n",buf);
16                         }
17                         exit(1)                //退出子进程
18                 }
19                 else{
20                       char writeBuf[3] = {'a','b','c'};
21                       close(pfd[0]);
22                       wirte(pfd[1],writeBuf,sizeof(writeBuf));     //向管道中写入数据
23                       exit(0);
24                 }
25            }
View Code

     b. 命名管道

 参考:http://www.cppblog.com/wanghaiguang/archive/2012/11/20/195412.html

posted on 2015-04-21 10:59  Crazy兔子  阅读(1140)  评论(0编辑  收藏  举报

导航