进程间通信之异步管道

来源:互联网 发布:mac pro双系统玩游戏 编辑:程序博客网 时间:2024/06/14 03:56

异步管道实现的流程图说明:
1)。父进程是我们需要实现的,其中需要创建管道A,管道B,和子进程,整个实现流程分为4个操作。
2)。管道A:输入管道
3)。管道B:输出管道
4)。操作A:把输入文件sample.in的数据写入输入管道(管道A)
5)。操作B:子进程从输入管道中读取数据,作为该进程的加工原料。通常,程序的输入数据由标准的输入设备输入,这里实现输入重定向,即把输入管道作为输入设备。
6)。操作C:子进程把加工后的成品(输出数据)输出到输出管道。通常,程序的输出数据会输出到标准的输出设备,一般为屏幕,这里实现输出重定向,即把输出管道作为输出设备。
7)。操作D:把输出管道的数据写入输出文件
需要注意的是,管道的本质只是一个共享的内存区域。这个实验中,管道区域处于父进程的地址空间中,父进程的作用是提供环境和资源,并协调子进程进行加工。

 

sample.exe实现:

#include <iostream.h>

int main()

 int a, b ; 

 while ( cin >> a >> b && ( a || b ) )   

 cout << a + b << endl ; 

 return 0;

}

 

Sample.in文件是输入文件,内容:
32 433
542 657
0 0

程序运行:

pipe.exe  sample.exe sample.in  sample.out

主程序pipe代码:

#include <windows.h>

#include <iostream.h>

 

const int BUFSIZE = 4096 ;

HANDLE       hChildStdinRd, hChildStdinWr, hChildStdinWrDup,

            hChildStdoutRd,hChildStdoutWr,hChildStdoutRdDup,

              hSaveStdin,         hSaveStdout;

 

BOOL CreateChildProcess(LPTSTR);

VOID WriteToPipe(LPTSTR);

VOID ReadFromPipe(LPTSTR);

VOID ErrorExit(LPTSTR);

VOID ErrMsg(LPTSTR, BOOL);

void main( int argc, char *argv[] )

{     

       // 处理输入参数

       if ( argc != 4 )

              return ;

 

       // 分别用来保存命令行,输入文件名(CPP/C),输出文件名(保存编译信息)

       LPTSTR lpProgram = new char( sizeof(argv[1]) ) ;

       strcpy ( lpProgram, argv[1] ) ;

       LPTSTR lpInputFile = new char( sizeof(argv[2]) ) ;

       strcpy ( lpInputFile, argv[2] ) ;

       LPTSTR lpOutputFile = new char( sizeof(argv[3]) ) ;

       strcpy ( lpOutputFile, argv[3] ) ;          

      

       SECURITY_ATTRIBUTES saAttr;

       saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);

       saAttr.bInheritHandle = TRUE;

       saAttr.lpSecurityDescriptor = NULL;

        

       /************************************************

        *           redirecting child process's STDOUT    *

        ************************************************/

       hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);

      

       if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))

              ErrorExit("Stdout pipe creation failed\n");

             

       if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))

              ErrorExit("Redirecting STDOUT failed");

      

       BOOL fSuccess = DuplicateHandle(

              GetCurrentProcess(),

              hChildStdoutRd,

        GetCurrentProcess(),

              &hChildStdoutRdDup ,

              0,

        FALSE,

        DUPLICATE_SAME_ACCESS);

    if( !fSuccess )

        ErrorExit("DuplicateHandle failed");

    CloseHandle(hChildStdoutRd);

      

       /************************************************

        *           redirecting child process's STDIN              *

        ************************************************/

       hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);

 

       if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))

              ErrorExit("Stdin pipe creation failed\n");

      

       if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))

              ErrorExit("Redirecting Stdin failed");

      

       fSuccess = DuplicateHandle(

              GetCurrentProcess(),

              hChildStdinWr,

              GetCurrentProcess(),

              &hChildStdinWrDup,

              0,

              FALSE,                

              DUPLICATE_SAME_ACCESS);

       if (! fSuccess)

              ErrorExit("DuplicateHandle failed");

       CloseHandle(hChildStdinWr);     

 

       /************************************************

        *                  创建子进程(即启动SAMPLE.EXE)             *

        ************************************************/

       fSuccess = CreateChildProcess( lpProgram );

       if ( !fSuccess )

              ErrorExit("Create process failed");

      

       // 父进程输入输出流的还原设置

       if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))

              ErrorExit("Re-redirecting Stdin failed\n");

       if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))

              ErrorExit("Re-redirecting Stdout failed\n");

 

       WriteToPipe( lpInputFile ) ;

       ReadFromPipe( lpOutputFile );

}

 

BOOL CreateChildProcess( LPTSTR lpProgram )

{

       PROCESS_INFORMATION piProcInfo;

       STARTUPINFO siStartInfo;

       BOOL bFuncRetn = FALSE;

      

       ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );

       ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );

       siStartInfo.cb = sizeof(STARTUPINFO);

      

       bFuncRetn = CreateProcess ( NULL, lpProgram, NULL, NULL, TRUE, \

                                                        0, NULL, NULL, &siStartInfo, &piProcInfo);

       if (bFuncRetn == 0)

       {

              ErrorExit("CreateProcess failed\n");

              return 0;

       }

       else

       {

              CloseHandle(piProcInfo.hProcess);

              CloseHandle(piProcInfo.hThread);

              return bFuncRetn;

       }

}

 

VOID WriteToPipe( LPTSTR lpInputFile )

{

       HANDLE hInputFile = CreateFile(lpInputFile, GENERIC_READ, 0, NULL,

              OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);

       if (hInputFile == INVALID_HANDLE_VALUE)

              return ;

 

       BOOL fSuccess ;

       DWORD dwRead, dwWritten;

       CHAR chBuf[BUFSIZE] = {0} ;

      

       for (;;)

       {

              fSuccess = ReadFile( hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ;

              if ( !fSuccess || dwRead == 0)

                     break;

 

              fSuccess = WriteFile( hChildStdinWrDup, chBuf, dwRead, &dwWritten, NULL) ;

              if ( !fSuccess )

                     break;

       }

             

       if (! CloseHandle(hChildStdinWrDup))

              ErrorExit("Close pipe failed\n");

 

       CloseHandle ( hInputFile ) ;

}

 

VOID ReadFromPipe( LPTSTR lpOutputFile )

{

       HANDLE hOutputFile = CreateFile( lpOutputFile, GENERIC_READ|GENERIC_WRITE,

              FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

       if (hOutputFile == INVALID_HANDLE_VALUE)

              return ;

 

       BOOL fSuccess ;

       DWORD dwRead, dwWritten;

       CHAR chBuf[BUFSIZE] = { 0 };

      

       if (!CloseHandle(hChildStdoutWr))

              ErrorExit("Closing handle failed");

      

       for (;;)

       {

              fSuccess = ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL) ;

              if( !fSuccess || dwRead == 0)

              {

                     break;

              }

              fSuccess = WriteFile( hOutputFile, chBuf, dwRead, &dwWritten, NULL) ;

              if ( !fSuccess )

                     break;

       }

 

       CloseHandle ( hOutputFile ) ;

}

VOID ErrorExit (LPTSTR lpszMessage)

{

       MessageBox( 0, lpszMessage, 0, 0 );

}

 

0 0
原创粉丝点击