windows下匿名管道

来源:互联网 发布:网络监控如何连接电脑 编辑:程序博客网 时间:2024/06/07 04:04

1.匿名管道的介绍:

    既然是匿名管道的话,自然,就是没有名字的管道了,还有一种管道呢,叫做命名管道,命名管道的功能是很强大的,匿名管道在命名管道面前,功能那是简陋的不行的,至于命名管道的话,以后才介绍,匿名管道正因为提供的功能很单一,所以它所需要的系统的开销也就比命名管道小很多,在本地机器上可以使用匿名管道来实现父进程和子进程之间的通信,这里需要注意两点,第一就是在本地机器上,这是因为匿名管道不支持跨网络之间的两个进程之间的通信,第二就是实现的是父进程和子进程之间的通信,而不是任意的两个进程。然后得话还顺便介绍匿名管道的另外一种功能,其通过匿名管道可以实现子进程输出的重定向。重定向后面文章会介绍。下面介绍一下匿名管道的使用:

(1)匿名管道主要用于本地父进程和子进程之间的通信,

(2)在父进程中的话,首先是要创建一个匿名管道,

(3)在创建匿名管道成功后,可以获取到对这个匿名管道的读写句柄,

(4)然后父进程就可以向这个匿名管道中写入数据和读取数据了,

(5)但是如果要实现的是父子进程通信的话,那么还必须在父进程中创建一个子进程,

(6)同时,这个子进程必须能够继承和使用父进程的一些公开的句柄,

(7)为什么呢?

(8)因为在子进程中必须要使用父进程创建的匿名管道的读写句柄,

(9)通过这个匿名管道才能实现父子进程的通信,所以必须继承父进程的公开句柄。

(10)同时在创建子进程的时候,

(11)必须将子进程的标准输入句柄设置为父进程中创建匿名管道时得到的读管道句柄,

(12)将子进程的标准输出句柄设置为父进程中创建匿名管道时得到的写管道句柄。

(13)然后在子进程就可以读写匿名管道了。

2 实例:


       当前有sample.cpp, sample.exe, sample.in这三个文件,sample.exe为sample.cpp的执行程序,sample.cpp只是一个简单的程序示例(简单求和),如下:

代码:
#include <iostream>using namespace std;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
       要求根据sample.exe和它的输入数据,把输出数据重定向到sample.out
流程分析:实际这个实验中包含两个部分,把输入数据重定向到sample.exe 和把输出数据重定向到sample.out。在命令行下可以很简单的实现这个功能“sample <sample.in >sample.out”,这个命令也是利用管道特性实现的,现在我们就根据异步管道的实现原理自己来实现这个功能。
管道是基于半双工(单向)的,这里有两个重定向的过程,显然需要创建两个管道,下面给出流程图:

     

匿名管道实现的流程图说明:
1)。父进程是我们需要实现的,其中需要创建管道A,管道B,和子进程,整个实现流程分为4个操作。
2)。管道A:输入管道
3)。管道B:输出管道
4)。操作A:把输入文件sample.in的数据写入输入管道(管道A)
5)。操作B:子进程从输入管道中读取数据,作为该进程的加工原料。通常,程序的输入数据由标准的输入设备输入,这里实现输入重定向,即把输入管道作为输入设备。
6)。操作C:子进程把加工后的成品(输出数据)输出到输出管道。通常,程序的输出数据会输出到标准的输出设备,一般为屏幕,这里实现输出重定向,即把输出管道作为输出设备。
7)。操作D:把输出管道的数据写入输出文件
需要注意的是,管道的本质只是一个共享的内存区域。这个实验中,管道区域处于父进程的地址空间中,父进程的作用是提供环境和资源,并协调子进程进行加工。
程序源码:
代码: 
 
#include<windows.h>#include<iostream>using namespace std;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 );int main(int argc,char* argv[]){    if(argc!=4)        return -1;    LPTSTR lpProgram=new char[strlen(argv[1])];    strcpy(lpProgram,argv[1]);    LPTSTR lpInputFile = new char[ strlen(argv[2]) ];    strcpy ( lpInputFile, argv[2] ) ;    LPTSTR lpOutputFile = new char[ strlen(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 );  delete lpProgram ;  delete lpInputFile ;  delete lpOutputFile ;  return 0;}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(LPSTR lpInputFile){  HANDLE hInputFile = CreateFile(lpInputFile, GENERIC_READ, FILE_SHARE_READ, NULL,    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);  if (hInputFile == INVALID_HANDLE_VALUE)  {      cout<<"open file error!"<<endl;      return ;  }  DWORD  fileSize = GetFileSize(hInputFile,NULL);          //得到文件的大小;  bool fSuccess ;  DWORD dwRead, dwWritten;  //DWORD filesize=GetFileSize(hInputFile,NULL); CHAR chBuf[fileSize] = {0} ; DWORD dwBytesToRead = fileSize; dwRead = 0; char* tmpBuf = chBuf;  do  {    fSuccess = ReadFile( hInputFile, tmpBuf, dwBytesToRead, &dwRead, NULL) ;    if (dwRead == 0)            break;    dwBytesToRead -= dwRead;    tmpBuf += dwRead;  }while(dwBytesToRead > 0);  fSuccess = WriteFile( hChildStdinWrDup, chBuf, dwRead, &dwWritten, NULL) ;    if ( !fSuccess )      return ;  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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 两个月的小孩子咳嗽怎么办 5个月宝宝吃奶少怎么办 26岁的1型糖尿病怎么办 睡前吃得太饱怎么办 胰岛素2小时>300怎么办 血清c肽测定高怎么办 体测蛋白质和骨骼肌偏高怎么办 半个月重了十斤怎么办 月经停了2个月怎么办 在练腹肌中腹痛怎么办 越练肌肉越肥怎么办 喘不过气来 心闷怎么办 被气得喘不过气怎么办 健身完头晕想吐怎么办 吃多了反胃头晕怎么办 合同未约定退货货物积压怎么办 运动内衣把胸压平怎么办 经常穿皮鞋脚臭怎么办 买衣服胸围小了怎么办 内衣下胸围太紧怎么办 穿文胸衣服要开怎么办 运动内衣的拉链老来怎么办 胸罩没干急着穿怎么办 跑步时大腿很痒怎么办 胖大腿内侧磨伤怎么办 内衣围带过松怎么办 内衣底围特别紧怎么办 全棉衣服上的油怎么办 高腰牛仔裤腰大了怎么办 新买衣服太硬怎么办 棉麻的衣服发硬怎么办 新衣服太硬怎么办雪纺 衣服硬的咯人怎么办 脖子上的勒痕怎么办 腿上容易出现勒痕怎么办 身上总有内裤印怎么办 内裤穿出了印怎么办 饮水机热水口不出水怎么办 饮水机热水口出水小怎么办 新饮水机热水口出水小怎么办 白钢水桶中间支撑怎么办