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 );
其中几个关键的形参为:
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);
参数pszCmdLine //用来指定传递给新进程的命令行字符串
1 TCHAR szApp[MAX_PATH] = TEXT("netstat -s"); 2 CreateProcess(NULL,szApp,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi);
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;
对于 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;
【注】CreateProcess()和CreateThread()的区别,是前者创建的是进程,而后者创建的是线程。
<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 }
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 }
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 }
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 }
b. 命名管道
参考:http://www.cppblog.com/wanghaiguang/archive/2012/11/20/195412.html