8、进程通信-匿名管道
匿名管道
一个单向,未命名的管道,通常用来在一个父进程和一个子进程间传输数据。只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。
BOOL CreatePipe(
PHANDLE hReadPipe, // read handle
PHANDLE hWritePipe, // write handle
LPSECURITY_ATTRIBUTES lpPipeAttributes, // security attributes
DWORD nSize // pipe size
);
CreateProcess 创建进程
创建父进程:
a. CreatePipe:其中第三个参数代表安全属性结构体SECURITY_ATTRIBUTES的指针,在前几章的运用中,都是运用了NULL,代表返回的安全句柄不可以被子进程所继承。但在本运用中,涉及到的是匿名管道。匿名管道就是父子进程之间的通信,所以结构体必须设置相应的值。子进程要想获得匿名管道的读写句柄,只能从父进程继承而来。一旦子进程有了继承而来的读写句柄,就可以和父进程进行通信了。对于机构体SECURITY_ATTRIBUTES,最重要的是第三个参数bInheritHandle,表示Specifies whether the returned handle is inherited when a new process is created. If this member is TRUE, the new process inherits the handle.
b. CreateProcess:如果创建管道成功,则创建子进程,并将管道的读写句柄传递给子进程。
1.MFC单文档程序菜单中增加创建管道,读取数据,写入数据三项
2.View类中增加成员变量
3. CreateProcess
倒数第三个参数 [in] Pointer to a STARTUPINFO structure that specifies how the main window for the new process should appear 指向STARTUPINFO结构体的一个指针,用来指定新的进程它的主窗口如何出现
最后一个参数指向PROCESS_INFORMATION结构体的一个指针的返回值,用来接收新的进程的标识信息
PROCESS_INFORMATION
The PROCESS_INFORMATION structure is filled in by the CreateProcess function with information
about a newly created process and its primary thread.
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;
Members
hProcess //新创建进程的句柄
A handle to the newly created process. The handle is used to specify the process in all
functions that perform operations on the process object.
hThread //新创建进程主线程的句柄
A handle to the primary thread of the newly created process. The handle is used to specify
the thread in all functions that perform operations on the thread object.
dwProcessId //全局进程标识符,如果进程结束操作系统可能会将标识分配给其他进程,我们调用标识的时候要确保进程在运行
A global process identifier that can be used to identify a process. The value is valid from the time the process is created until the time the process is terminated.
dwThreadId //全局线程标识符
A global thread identifiers that can be used to identify a thread. The value is valid from the
time the thread is created until the time the thread is terminated.
创建匿名管道具体代码:
SECURITY_ATTRIBUTES sa;
//总共就三个参数
sa.bInheritHandle=TRUE; //表示可被子进程所继承
sa.lpSecurityDescriptor=NULL; //安全描述符号一般都设置成NULL,即默认描述符
sa.nLength=sizeof(SECURITY_ATTRIBUTES); //管道长度
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
MessageBox("创建匿名函数失败!");
return;
}
//管道创建成功后,接着创建子进程,并将读写句柄传递给子进程
STARTUPINFO sui;
PROCESS_INFORMATION pi;
//调用ZeroMemory方法将该结构体中的所有成员都置为0,这是因为这个结构体的成员很多,如果开始的时候没有置为0的话,那它的值是随机的,将这样的结构体传给CreateProcess,可能会影响到执行的结果。
ZeroMemory(&sui,sizeof(STARTUPINFO));
sui.cb=sizeof(STARTUPINFO); //设置结构体的大小
sui.dwFlags=STARTF_USESTDHANDLES; //该标识表示标准输入句柄,标准输出句柄和错误句柄是有用的
sui.hStdInput=hRead; //将子进程的输入句柄设置成父进程的读句柄
sui.hStdOutput=hWrite; //将子进程的输出句柄设置成父进程的写句柄
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE); //得到标准错误句柄,是父进程的错误句柄,该行代码在本程序中没有实际的用途意义
//因为是匿名管道,是没有名称的管道,只有通过CreateProcess由上而下的传递管道操作句柄。
if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,NULL,NULL,
TRUE,0,NULL,NULL,&sui,π))
{
MessageBox("创建子进程失败!");
CloseHandle(hRead);
CloseHandle(hWrite);
//避免在析构函数中再次关闭,析构函数采用:
//if(hRead) CloseHandle(hRead)
hRead=NULL;
hWrite=NULL;
return;
}
else
{
//创建一个新的进程的时候,系统会创建一个进程内核对象和一个线程内核对象,内核对象都有一个使用基数,初始调用的时候,都设置为1。在CreateProcess返回之前,该函数打开进程和线程的内核对象,并将进程相关的句柄放置到结构体PROCESS_INFORMATION的hProcess和hThread中,当Process在内部打开这些对象的时候,使得每个对象的使用基数增加到2了。如果在父进程中不需要使用这两个句柄,就将这个句柄进行关闭,使得使用基数减1。当子进程终结的时候,系统会在将使用基数减1,使得子进程的进程内核对象和线程内核对象的使用基数变为0,这样内核对象就可以被释放了。
CloseHandle(pi.hProcess); //关闭子进程的句柄
CloseHandle(pi.hThread); //关闭子进程中主线程的句柄
}
父进程写匿名管道:
char *buf="hello world";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("匿名管道写入数据失败!");
return;
}
父进程读匿名管道:
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
MessageBox("匿名管道读取数据失败!");
return;
}
MessageBox(buf);
创建子进程程序:
可以将获取父进程的匿名管道的读写句柄操作放在CView类的OnInitialUpdate方法中实现,该方法是在CView完全构造后调用的第一个方法。代码如下:
hRead=GetStdHandle(STD_INPUT_HANDLE);
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
子进程的读写匿名管道的代码和父进程的一样,这里不再累述。
为了让子进程从众多继承的句柄中区分出管道的读、写句柄,就必须将子进程的特殊句柄设置为管道的读写句柄。
参考
[1]MSDN
[2]《VC++ 深入》
[3]http://blog.csdn.net/liufei_learning/archive/2009/12/17/5026410.aspx
8、进程通信-匿名管道相关推荐
- Linux进程通信——匿名管道、命名管道、管道的特性和共享内存
Linux进程通信--匿名管道.命名管道.管道的特性和共享内存 一.管道 1.1 什么是管道? 1.2 匿名管道 <1> 匿名管道参数说明 <2> fork共享管道原理 < ...
- 2.12父子进程通过匿名管道通信
目录 1.pipe函数 2.查看管道缓冲大小 1.pipe函数 #include <unistd.h> int pipe(int pipefd[2]);功能:创建一个匿名管道,用来进程间通 ...
- Linux编程:多个子进程与父进程使用匿名管道读写
编写程序,在程序中父进程先后创建子进程1和子进程2.父子三个进程并发执行,并利用同一个匿名管道通信:两个子进程分别向管道写一则信息(内容自定,但要求包含子进程信息):父进程从管道读出信息并显示出来(要 ...
- 【Linux系统编程】进程通信之管道
1.进程间通信介绍 1.1 进程通信的基本概念 在之前我们已经学习过进程地址空间.Linux 环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不 ...
- 进程通信——命名管道
目录 1.Creat 2.Open 3.Read/Write 4.Wait 5.Close 6.Delete 管道是 SylixOS 进程间通信的一种方式. 管道分为匿名管道 pipe 和命名管道 f ...
- php管道邮件,php进程通信-PIPE管道通信
上一篇文章讲到了php进程通信的进程信号通信方法,本文介绍的是有名管道: 管道通信,主要是利用文件,写入以及读取来进行通信的, 通俗来讲,就是A进程在1.txt写入1,B进程读取1.txt,就能读取到 ...
- Linux进程通信之管道
进程间完成数据传递需要借助操作系统提供的特殊的方法,比如:文件.管道.信号.共享内存.消息队列.套接字.命名管道等.但现在常用的进程间通信方式有: 管道 – 使用最简单 pipe 管道一般读写行为 F ...
- 6.进程通信 无名管道 有名管道
进程间通信(IPC,InterProcess Communication) 概念:就是进程和进程之间交换信息. 常用通信方式 无名管道(pipe) 有名管道 (fifo) 信号(signal) 共享内 ...
- linux通信管道破裂,Linux下进程通信之管道
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把 ...
- 进程通信:管道(pipe)和socketpair区别
管道pipe是半双工的,pipe两次才能实现全双工,使得代码复杂.socketpair直接就可以实现全双工 socketpair对两个文件描述符中的任何一个都可读和可写,而pipe是一个读,一个写 详 ...
最新文章
- Hibernate学习(九)———— 二级缓存和事务级别详讲
- STL queue priority_queue
- 一文了解可视化的主成分分析(附教程)
- deeplearning URL
- redis 附近的人_Redis GEO地理位置信息,查看附近的人
- Bash脚本教程之行操作
- 【C++】rand函数的基本使用
- 前端学习(1898)vue之电商管理系统电商系统之渲染用户的对话框
- echarts mysql_ECharts实现mysql 数据图表化
- 八年级信息技术认识计算机网络,初二信息技术课名称:认识计算机网络.doc
- es 时间字段聚合_ES聚合命令
- [2019上海网络赛F题]Rhyme scheme
- windowForm资料
- Windows 实时语音转文字|免费语音视频翻译转文字|语音会议记录方案
- 栈的链式表示+判断表达式括号是否配对
- Nginx实现高可用
- win8计算机可用内存不足,win8电脑运行提示物理内存不足的解决方法
- 浏览器拍照功能(Vue+ElementUI组件)
- Kafka之消费全流程
- C++新特性——郭炜