管道的分类

管道其实际就是一段共享内存,只不过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)----管道的更多相关文章

  1. High Performance Networking in Google Chrome 进程间通讯(IPC) 多进程资源加载

    小结: 1. 小文件存储于一个文件中: 在内部,磁盘缓存(disk cache)实现了它自己的一组数据结构, 它们被存储在一个单独的缓存目录里.其中有索引文件(在浏览器启动时加载到内存中),数据文件( ...

  2. Android AIDL 进行进程间通讯(IPC)

    编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...

  3. QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开     本文地址:h ...

  4. Windows进程间通讯(IPC)----消息队列

    消息队列 windows系统是通过消息驱动的,每移动一下鼠标,点击一下屏幕都会产生一个消息.这些消息会先被放在windows的一个系统消息队列(先进先出)中,windows系统会为每一个GUI线程创建 ...

  5. Windows进程间通讯(IPC)----共享内存

    Windows中同一个EXE文件多次加载过程 Windows中EXE文件加载是基于内存映射文件的. 当EXE文件第一次被加载. 首先系统会先创建一个进程内核对象,并创建一个新的进程地址空间. 系统调用 ...

  6. Windows进程间通讯(IPC)----内存映射文件

    内存映射文件原理 内存映射文件是通过在虚拟地址空间中预留一块区域,然后通过从磁盘中已存在的文件为其调度物理存储器,访问此虚拟内存空间就相当于访问此磁盘文件了. 内存映射文件实现过程 HANDLE hF ...

  7. Windows进程间通讯(IPC)----WM_COPYDATA

    WM_COPYDATA通讯思路 通过向其他进程的窗口过程发送WM_COPYDATA消息可以实现进程间通讯. 只能通过SendMessage发送WM_COPYDATA消息,而不能通过PostMessag ...

  8. 服务 远程服务 AIDL 进程间通讯 IPC

    Activity aidl接口文件 package com.bqt.aidlservice;  interface IBinderInterface {     /* 更改文件后缀为[.aidl]去掉 ...

  9. Windows进程间通讯(IPC)----信号量

    线程同步内核对象 操作系统进行进程间同步是利用信号量机制.对于windows系统而言,可以利用一些内核对象进行线程同步,因为这些内核对象可以命名并且属于系统内核,所以可以支持不同进程间的线程同步进而实 ...

随机推荐

  1. 攻防世界 reverse 2ex1

    2ex1 CISCN-2018-Quals mark 1 import base64 2 3 std_base= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk ...

  2. [树形DP]加分二叉树

    加 分 二 叉 树 加分二叉树 加分二叉树 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第j ...

  3. vue-router 监控全局路由,在路由中改变vuex中的状态值

  4. 常用Linux操作

    常用Linux操作 这里我使用的是Git进行的Linux操作,如果你有服务器.或者LInux系统可以直接尝试 首先保证自己电脑上成功安装好了Git,右键鼠标: 随便找一个文件夹(我这里使用的是桌面的G ...

  5. malloc函数详解 glibc2.27

    malloc 函数分析(glibc.2.27) 本人菜一只,如果分析的有错误,请大佬指正. __libc_malloc函数分析 void * __libc_malloc (size_t bytes) ...

  6. Go-06-数据类型、常量、运算符

    数据类型转换 Go语言采用数据类型前置加括号的方式进行类型转换,格式如:T(表达式).T表示要转换的类型:表达式包括变量.数值.函数返回值等. var a int =100 b := float(a) ...

  7. 数据结构之Queue | 让我们一块来学习数据结构

    前面的两篇文章分别介绍了List和Stack,下面让我们一起来学习Queue 数据结构之List | 让我们一块来学习数据结构 数据结构之Stack | 让我们一块来学习数据结构 队列的概况 队列是一 ...

  8. 善用k8s describe

    使用 kubectl describe 来查看某个东西的详细例如 kubectl describe deployment my-nginx kubectl describe svc my-nginx

  9. Java基础常用类深度解析(包含常见排序算法)

    目录 一.工具类 1.1.工具类的设计 1.1.1.公共静态方法 1.2.单例模式 二.包装类 2.1.基本类型的包装类 2.1.1.Integer 2.1.1.1.Integer >> ...

  10. pyqt5 菜单栏+信息提示框

    前言 使用pyqt5 添加菜单栏 单击菜单栏 弹出信息框(MessageBox用法) 菜单栏 功能 Action是Qt中单独引入的一个对象,对应QAction类.Action表示一个独立的操作,是将界 ...