进程间通信(1):匿名管道

xiaoxiao2021-02-28  98

进程可以理解为一个独立的程序和其支配的内存空间,是程序运行的实体。进程拥有独立的内存空间,在两个进程间实现数据共享相对线程要困难一些。在这系列文章中,对不同的进程间数据共享方式进行说明,并通过C++实例进行实现讲解。

搜索一下网上进程间通信方式,比较夸张的是说有“十一”种方法,方法虽多,但是基本原理都是相通的,一个东西不同包装而已。其实掌握主要方法,既可以应对日常的工作。本系列文章从常用方法说起,争取覆盖所有见得到的方法。

管道通信的方式,是通过建立管道文件,实现进程间的信息传输通道。

 

管道是常用的进程间通信方式,管道主要分为匿名管道和命名管道两种。

 

这里首先讲解匿名管道,余下的在后续文章中介绍。(这里插一句, “匿”的拼音为nin,写到这里要感慨一下自己的语文,学的还是有瑕疵。)

 

管道信息传输遵循“先入先出”(FIFO)原则,即先写入管道的信息,会被首先读取出来。

 

匿名管道(“Anonymous Pipe”)是管道中的一种,该类管道在使用过程中,有比较多的限制。匿名管道只能用于父子进程间的通信,这里我们定义父进程为程序的第一次入口,子进程是在父进程中,通过程序产生的进程,二者拥有了天然的亲缘关系。这种亲缘关系使得通信参数的传递更加便捷,可通过“标准读句柄”和“标准写句柄”在进程中获得管道文件的标识,从而实现通信。

 

结合例子进行讲解,例程如下。由于子进程必须由父进程创建,为了简化程序,这里将父进程和子进程写于同一主函数中,通过参数决定父子进程代码的不同。

 

父进程无输入参数,父进程首先创建管道,匿名管道传输中的管道必须由父进程创建,创建管道后启动子进程,在子进程的命令行中添加参数,实现进程的功能控制。在创建进程后,向管道写入数据,程序暂停,等待子进程读取。

 

子进程创建后,通过标准输入句柄获取管道文件,并从中读取父进程写入的信息,实现匿名管道通信。

 

注:此例为Windows平台下编程实例,应用windows平台封装的管道API实现通信。

文章中示例代码的完整工程文件可在http://download.csdn.net/detail/ezhchai/9895267中下载。

#include "stdafx.h" #include <windows.h> #include <iostream> using namespace std; int main(int argc, char* argv[]) { if (argc > 1) { /* * * 子进程 * * */ cout << "Child Process" << endl; /* * 接收管道数据,并显示 * */ CHAR szBuffer[16]{ 0 }; ReadFile(GetStdHandle(STD_INPUT_HANDLE), szBuffer, sizeof(szBuffer), nullptr, nullptr); cout << szBuffer << endl; } else { /* * * 父进程 * * */ cout << "Parent Process" << endl; HANDLE hPipeW = NULL, hPipeR = NULL; //读管道句柄和写管道句柄 //安全性结构 SECURITY_ATTRIBUTES sa{ 0 }; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE;//填充安全性结构使句柄被继承 // 创建匿名管道 if (!CreatePipe(&hPipeR, &hPipeW, &sa, 0)) { cout << "Create pipe failed! Processs return!" << endl; return 1; } // 进程信息结构体 PROCESS_INFORMATION pi{ 0 }; // 进程启动窗体信息结构体 STARTUPINFOA si{ 0 }; si.cb = sizeof(si); si.hStdInput = hPipeR; si.dwFlags = STARTF_USESTDHANDLES; // 为子进程命令行添加参数 char param[1024]; sprintf_s(param, "%s %s", argv[0], "test"); // 创建子进程 if (!CreateProcessA(nullptr, param, nullptr, nullptr, TRUE, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) { CloseHandle(hPipeR); CloseHandle(hPipeW); cout << "Create child process failed! Process return!" << endl; return 2; } // 写管道数据 WriteFile(hPipeW, "ezhchai", 7, nullptr, nullptr); } system("pause"); return 0; }

转载请注明原文地址: https://www.6miu.com/read-66095.html

最新回复(0)