• 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] = '';
    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.
    "<<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',''};
    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
    ",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

  • 相关阅读:
    牛客(46)孩子们的游戏(圆圈中最后剩下的数)
    牛客(45)扑克牌顺子
    牛客(44)翻转单词顺序列
    牛客(43)左旋转字符串
    牛客(42)和为S的两个数字
    牛客(41)和为S的连续正数序列
    牛客(40)数组中只出现一次的数字
    牛客(39)平衡二叉树
    牛客(38)二叉树的深度
    牛客(37)数字在排序数组中出现的次数
  • 原文地址:https://www.cnblogs.com/felixpan/p/4441993.html
Copyright © 2020-2023  润新知