cc++管道编程

cc++管道编程

2023年8月1日发(作者:)

cc++管道编程概述  管道(Pipe)实际是⽤于进程间通信的⼀段共享内存,创建管道的进程称为管道服务器,连接到⼀个管道的进程为管道客户机。⼀个进程在向管道写⼊数据后,另⼀进程就可以从管道的另⼀端将其读取出来。匿名管道(Anonymous Pipes)是在⽗进程和⼦进程间单向传输数据的⼀种未命名的管道,只能在本地计算机中使⽤,⽽不可⽤于⽹络间的通信。  匿名管道实施细则  匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针 PHANDLE hWritePipe, // 指向写句柄的指针 LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针 DWORD nSize // 管道⼤⼩);  通过hReadPipe和hWritePipe所指向的句柄可分别以只读、只写的⽅式去访问管道。在使⽤匿名管道通信时,服务器进程必须将其中的⼀个句柄传送给客户机进程。句柄的传递多通过继承来完成,服务器进程也允许这些句柄为⼦进程所继承。除此之外,进程也可以通过诸如DDE或共享内存等形式的进程间通信将句柄发送给与其不相关联的进程。  在调⽤CreatePipe()函数时,如果管道服务器将lpPipeAttributes 指向的SECURITY_ATTRIBUTES数据结构的数据成员bInheritHandle设置为TRUE,那么CreatePipe()创建的管道读、写句柄将会被继承。管道服务器可调⽤DuplicateHandle()函数改变管道句柄的继承。管道服务器可以为⼀个可继承的管道句柄创建⼀个不可继承的副本或是为⼀个不可继承的管道句柄创建⼀个可继承的副本。CreateProcess()函数还可以使管道服务器有能⼒决定⼦进程对其可继承句柄是全部继承还是不继承。  在⽣成⼦进程之前,⽗进程⾸先调⽤Win32 API SetStdHandle()使⼦进程、⽗进程可共⽤标准输⼊、标准输出和标准错误句柄。当⽗进程向⼦进程发送数据时,⽤SetStdHandle()将管道的读句柄赋予标准输⼊句柄;在从⼦进程接收数据时,则⽤SetStdHandle()将管道的写句柄赋予标准输出(或标准错误)句柄。然后,⽗进程可以调⽤进程创建函数CreateProcess()⽣成⼦进程。如果⽗进程要发送数据到⼦进程,⽗进程可调⽤WriteFile()将数据写⼊到管道(传递管道写句柄给函数),⼦进程则调⽤GetStdHandle()取得管道的读句柄,将该句柄传⼊ReadFile()后从管道读取数据。  如果是⽗进程从⼦进程读取数据,那么由⼦进程调⽤GetStdHandle()取得管道的写⼊句柄,并调⽤WriteFile()将数据写⼊到管道。然后,⽗进程调⽤ReadFile()从管道读取出数据(传递管道读句柄给函数)。  在⽤WriteFile()函数向管道写⼊数据时,只有在向管道写完指定字节的数据后或是在有错误发⽣时函数才会返回。如管道缓冲已满⽽数据还没有写完,WriteFile()将要等到另⼀进程对管道中数据读取以释放出更多可⽤空间后才能够返回。管道服务器在调⽤CreatePipe()创建管道时以参数nSize对管道的缓冲⼤⼩作了设定。  匿名管道并不⽀持异步读、写操作,这也就意味着不能在匿名管道中使⽤ReadFileEx()和WriteFileEx(),⽽且ReadFile()和WriteFile()中的lpOverLapped参数也将被忽略。匿名管道将在读、写句柄都被关闭后退出,也可以在进程中调⽤CloseHandle()函数来关闭此句柄。

匿名管道程序⽰例  总的来说,匿名管道程序是⽐较简单的。在下⾯将要给出的程序⽰例中,将由⽗进程(管道服务器)创建⼀个⼦进程(管道客户机),⼦进程回见个其全部的标准输出发送到匿名管道中,⽗进程再从管道读取数据,⼀直到⼦进程关闭管道的写句柄。其中,匿名管道服务器程序的实现清单如下:STARTUPINFO si;PROCESS_INFORMATION pi;char ReadBuf[100];DWORD ReadNum;HANDLE hRead; // 管道读句柄HANDLE hWrite; // 管道写句柄BOOL bRet = CreatePipe(&hRead, &hWrite, NULL, 0); // 创建匿名管道if (bRet == TRUE) printf("成功创建匿名管道!n");else printf("创建匿名管道失败,错误代码:%dn", GetLastError()); // 得到本进程的当前标准输出 HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE); // 设置标准输出到匿名管道 SetStdHandle(STD_OUTPUT_HANDLE, hWrite); GetStartupInfo(&si); // 获取本进程的STARTUPINFO结构信息 bRet = CreateProcess(NULL, "", NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi); // 创建⼦进程 SetStdHandle(STD_OUTPUT_HANDLE, hTemp); // 恢复本进程的标准输出 if (bRet == TRUE) // 输⼊信息  printf("成功创建⼦进程!n"); else  printf("创建⼦进程失败,错误代码:%dn", GetLastError());  CloseHandle(hWrite); // 关闭写句柄  // 读管道直⾄管道关闭  while (ReadFile(hRead, ReadBuf, 100, &ReadNum, NULL))  {   ReadBuf[ReadNum] = '';   printf("从管道[%s]读取%d字节数据n", ReadBuf, ReadNum);  }  if (GetLastError() == ERROR_BROKEN_PIPE) // 输出信息   printf("管道被⼦进程关闭n");  else   printf("读数据错误,错误代码:%dn", GetLastError());  在本⽰例中,将当前进程的标准输出设置为使⽤匿名管道,再创建⼦进程,⼦进程将继承⽗进程的标准输出,然后再将⽗进程的标准输出恢复为其初始状态。于是⽗进程便可从管道读取数据,直到有错误发⽣或关闭管道写⼊端的所有句柄。创建的⼦进程只是向标准输出和标准错误发送⼀些⽂本信息,其中发送给标准输出的⽂本将重定向输出到管道,发送给标准错误的⽂本将不改变输出。下⾯给出⼦进程的实现代码:int main(int argc, char* argv[]){ for (int i = 0; i < 100; i++) // 发送⼀些数据到标准输出和标准错误 {  printf("i = %dn", i); // 打印提⽰  cout << "标准输出:" << i << endl; // 打印到标准输出  cerr << "标准错误:" << i << endl; // 打印到标准错误 } return 0;}

发布者:admin,转转请注明出处:http://www.yc00.com/news/1690873809a452148.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信