Windows进程间通讯(IPC)----管道
管道的分类
管道其实际就是一段共享内存,只不过Windows规定需要使用I/O的形式类访问这块共享内存,管道可以分为匿名管道和命名管道。
- 匿名管道就是没有名字的管道,其支持单向传输数据,如果需要双向传送数据就需要创建两条管道。而且其只支持具有父子关系的两个进程进行通信,不能在网络间进行通信。
- 命名管道就是有名字的管道,其支持双向传输数据,因此一般还需要创建一条命名管道实现两个进程间的通讯。他的实现类似于我们了解的客户端/服务端。他能在任意进程间进行通讯。
匿名管道
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength; //结构大小
LPVOID lpSecurityDescriptor; //安全属性(一般为NULL采用默认属性)
BOOL bInheritHandle; //管道句柄是否可继承
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
匿名管道在创建前需要设置其安全描述符结构,此结构的bInheritHandle字段规定管道句柄是否可继承,也就是其此进程的子进程是否可以继承此管道句柄,如果不能继承那么子进程就无法使用此管道句柄进行管道数据的读写。
BOOL CreatePipe(
PHANDLE hReadPipe, //保存管道用来读数据的管道句柄的指针
PHANDLE hWritePipe, //保存管道用来写数据的管道句柄的指针
LPSECURITY_ATTRIBUTES lpPipeAttributes,
DWORD nSize
);
利用CreatePipe()创建匿名管道,nSize指定为管道缓冲区的大小,如果值为0就采用默认大小。
//伪代码
SECURITY_ATTRIBUTES.dwFlags = STARTF_USESTDHANDLES;
bInheritHandles = TRUE;
接着就是创建子进程,然后通过管道与此子进程进行通信。创建此子进程的STARTUPINFO结构的dwFlags字段要为STARTF_USESTDHANDLES这样改变子进程的标准输入输出才有效,否则无效。CreateProcess创建子进程时其第五个参数bInheritHandles要为TRUE,表示此进程创建的子进程可以继承本进程的句柄,这样本进程创建的管道句柄才能被子进程使用用来与本进程通信。
BOOL WriteFile(
HANDLE hFile, //对应写数据的管道句柄
LPCVOID lpBuffer, //保存写入数据的缓冲区
DWORD nNumberOfBytesToWrite, //写入数据的大小
LPDWORD lpNumberOfBytesWritten, //返回实际写入数据的大小
LPOVERLAPPED lpOverlapped //异步操作一般为NULL
);
BOOL ReadFile(
HANDLE hFile, //对应读数据的管道句柄
LPVOID lpBuffer, //保存读取数据的缓冲区
DWORD nNumberOfBytesToRead, //读取数据缓冲区的大小
LPDWORD lpNumberOfBytesRead, //返回实际读取的数据大小
LPOVERLAPPED lpOverlapped ////异步操作一般为NULL
);
之后就通过WriteFile()和ReadFile()利用对应的管道句柄来通过管道与子进程进行通信。
HANDLE hMyWrite, hMyRead, hCmdWrite, hCmdRead;
void _Init()
{
SECURITY_ATTRIBUTES as; //安全描述符结构
as.nLength = sizeof(SECURITY_ATTRIBUTES);
as.bInheritHandle = TRUE; //管道句柄可继承
as.lpSecurityDescriptor = NULL; //NULL表示使用默认的安全属性
CreatePipe(&hCmdRead, &hMyWrite, &as, 0); // my ----> cmd 管道
CreatePipe(&hMyRead, &hCmdWrite, &as, 0); // my <---- cmd 管道
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES; //意思是可以更改cmd的标准输入输出
si.hStdInput = hCmdRead; //子进程的标准输入为my ----> cmd管道的读管口
si.hStdOutput = hCmdWrite; //子进程的标准输入为my <---- cmd管道的写管口
si.hStdError = hCmdWrite;
CreateProcess(TEXT("C:\\Windows\\System32\\cmd.exe"),
NULL,
NULL,
NULL,
TRUE, //句柄可继承
CREATE_NO_WINDOW,
NULL,
NULL,
&si,
&pi);
}
int main(int argc, char* argv[])
{
_Init(); //初始化管道
char szWriteBuffer[MAX_PATH];
printf("%s", "请输入需要执行的cmd命令:");
scanf("%s", szWriteBuffer);
WriteFile(hMyWrite, szWriteBuffer, sizeof(szWriteBuffer), NULL, NULL); //向管道中写数据
Sleep(1);
DWORD dwSize; //每次从管道中读取数据的大小
char szBuffer1[MAX_PATH];
char szBuffer2[0x1000]; //存放最终的数据
while(1) //循环读取
{
memset(szBuffer1, 0, sizeof(szBuffer1));
ReadFile(hMyRead, szBuffer1, MAX_PATH, &dwSize, NULL); //从管道中读取数据
lstrcat(szBuffer2, szBuffer1);
if (dwSize != MAX_PATH)
break;
}
printf("cmd的返回为:\n%s:", szBuffer2);
return 0;
}
上面的例子通过建立本进程与cmd进程之间的两条匿名管道进行数据的传递。
命名管道
利用命名管道进行两个进程间的通讯就类似于将两个进程一个当成服务端,一个当成客户端。
HANDLE CreateNamedPipeA(
LPCSTR lpName, //管道名称
DWORD dwOpenMode, //打开模式(单向还是双向)
DWORD dwPipeMode, //管道模式
DWORD nMaxInstances, //此管道最大的实例数
DWORD nOutBufferSize, //一般为0
DWORD nInBufferSize, //一般为0
DWORD nDefaultTimeOut, //表示管道的默认等待超时,NMPWAIT_WAIT_FOREVER表示一直等待
LPSECURITY_ATTRIBUTES lpSecurityAttributes //使用默认安全属性NULL
);
服务端创建命名管道返回管道句柄,管道的名称需要遵循入下格式\.\pipe\name,名字最长为256个字符。
BOOL ConnectNamedPipe(
HANDLE hNamedPipe, //命名管道句柄
LPOVERLAPPED lpOverlapped //一般为NULL
);
服务端创建完命名管道后就是等待客户端连接。
BOOL WaitNamedPipeA(
LPCSTR lpNamedPipeName, //命名管道名称
DWORD nTimeOut //等待时长,NMPWAIT_WAIT_FOREVER表示一直等待
);
客户端通过命名管道的名称连接服务端。
连接成功后通过CreateFile()打开命名管道并获得管道句柄,接着利用管道句柄通过ReadFile()和WriteFile()进行通讯。
Windows进程间通讯(IPC)----管道的更多相关文章
- High Performance Networking in Google Chrome 进程间通讯(IPC) 多进程资源加载
小结: 1. 小文件存储于一个文件中: 在内部,磁盘缓存(disk cache)实现了它自己的一组数据结构, 它们被存储在一个单独的缓存目录里.其中有索引文件(在浏览器启动时加载到内存中),数据文件( ...
- Android AIDL 进行进程间通讯(IPC)
编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...
- QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开 本文地址:h ...
- Windows进程间通讯(IPC)----消息队列
消息队列 windows系统是通过消息驱动的,每移动一下鼠标,点击一下屏幕都会产生一个消息.这些消息会先被放在windows的一个系统消息队列(先进先出)中,windows系统会为每一个GUI线程创建 ...
- Windows进程间通讯(IPC)----共享内存
Windows中同一个EXE文件多次加载过程 Windows中EXE文件加载是基于内存映射文件的. 当EXE文件第一次被加载. 首先系统会先创建一个进程内核对象,并创建一个新的进程地址空间. 系统调用 ...
- Windows进程间通讯(IPC)----内存映射文件
内存映射文件原理 内存映射文件是通过在虚拟地址空间中预留一块区域,然后通过从磁盘中已存在的文件为其调度物理存储器,访问此虚拟内存空间就相当于访问此磁盘文件了. 内存映射文件实现过程 HANDLE hF ...
- Windows进程间通讯(IPC)----WM_COPYDATA
WM_COPYDATA通讯思路 通过向其他进程的窗口过程发送WM_COPYDATA消息可以实现进程间通讯. 只能通过SendMessage发送WM_COPYDATA消息,而不能通过PostMessag ...
- 服务 远程服务 AIDL 进程间通讯 IPC
Activity aidl接口文件 package com.bqt.aidlservice; interface IBinderInterface { /* 更改文件后缀为[.aidl]去掉 ...
- Windows进程间通讯(IPC)----信号量
线程同步内核对象 操作系统进行进程间同步是利用信号量机制.对于windows系统而言,可以利用一些内核对象进行线程同步,因为这些内核对象可以命名并且属于系统内核,所以可以支持不同进程间的线程同步进而实 ...
随机推荐
- 从RocketMQ的Broker源码层面验证一下这两个点
本篇博客会从源码层面,验证在RocketMQ基础概念剖析,并分析一下Producer的底层源码中提到的结论,分别是: Broker在启动时,会将自己注册到所有的NameServer上 Broker在启 ...
- VUE移动端音乐APP学习【四】:scroll组件及loading组件开发
scroll组件 制作scroll 组件,然后嵌套一个 DOM 节点,使得该节点就能够滚动.该组件中需要引入 BetterScroll 插件. scroll.vue: <template> ...
- java例题_47 读取 7 个数(1—50)的整数值,每读取一个值,程序打印出该值个数的*
1 /*47 [程序 47 打印星号] 2 题目:读取 7 个数(1-50)的整数值,每读取一个值,程序打印出该值个数的*. 3 */ 4 5 /*分析 6 * 1.多次读取---for循环 7 * ...
- OxyPlot.SkiaSharp显示中文乱码的问题
oxyplot 图表控件功能强大,使用很广泛.最近考虑到性能使用OxyPlot.SkiaSharp替代OxyPlot.WPF,曲线图表初步测试,性能提升近10倍左右.基于SkiaSharp图形引擎的一 ...
- jQuery核心函数和静态方法
jQuery核心函数 从jQuery文档中可以看出,jQuery核心函数一共3大类4小类 jQuery(callback) 当DOM加载完成后执行传入的回调函数 <script> $(fu ...
- OO第一单元总结与反思
OO第一单元总结与反思 目录 OO第一单元总结与反思 摘要 第一次作业 本次作业UML类图 本次作业度量分析 第二次作业 本次作业的UML类图 本次作业的度量分析 第三次作业 本次作业的UML类图: ...
- 记一次在virtualbox中安装windows7遇到增强功能安装分辨率的问题
在windows7中遇到很多次安装好增强功能后并不能对其实现放大分辨率,使其跟随虚拟机界面大小而改变. 经过许多次的安装和恢复快照,发现了在设置中,显存的大小一直都是处于边缘的状态, 关闭虚拟机后,我 ...
- 4. Linux-startx命令
Linux系统startx命令的功能和使用方法 Linux系统命令startx的功能很简单,就是启动X Window的服务这一项,没有其他的了.其实startx命令启动的是xinit,然后再由xini ...
- Ugly Numbers UVA - 136
Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9 ...
- JDBC_12_JDBC事务
JDBC事务 JDBC中事务默认自动提交,每执行一次SQL就会自动提交一次. 这样的话可能出现数据安全性问题. connection.setAutoCommit(false) false代表关闭自动提 ...