8、进程通信-匿名管道

简介: 匿名管道 一个单向,未命名的管道,通常用来在一个父进程和一个子进程间传输数据。只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。 BOOL CreatePipe(   PHANDLE hReadPipe,                       // read handle ...

匿名管道

一个单向,未命名的管道,通常用来在一个父进程和一个子进程间传输数据。只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。

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_INFORMATIONhProcesshThread中,当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);

子进程的读写匿名管道的代码和父进程的一样,这里不再累述。

    为了让子进程从众多继承的句柄中区分出管道的读、写句柄,就必须将子进程的特殊句柄设置为管道的读写句柄。

参考

1MSDN

2]《VC++ 深入》

3http://blog.csdn.net/liufei_learning/archive/2009/12/17/5026410.aspx 

目录
相关文章
|
21天前
|
存储 Unix Linux
进程间通信方式-----管道通信
【10月更文挑战第29天】管道通信是一种重要的进程间通信机制,它为进程间的数据传输和同步提供了一种简单有效的方法。通过合理地使用管道通信,可以实现不同进程之间的协作,提高系统的整体性能和效率。
|
21天前
|
消息中间件 存储 供应链
进程间通信方式-----消息队列通信
【10月更文挑战第29天】消息队列通信是一种强大而灵活的进程间通信机制,它通过异步通信、解耦和缓冲等特性,为分布式系统和多进程应用提供了高效的通信方式。在实际应用中,需要根据具体的需求和场景,合理地选择和使用消息队列,以充分发挥其优势,同时注意其可能带来的复杂性和性能开销等问题。
|
1月前
|
存储 Python
Python中的多进程通信实践指南
Python中的多进程通信实践指南
23 0
|
2月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
340 4
|
2月前
|
消息中间件 Unix Linux
C语言 多进程编程(二)管道
本文详细介绍了Linux下的进程间通信(IPC),重点讨论了管道通信机制。首先,文章概述了进程间通信的基本概念及重要性,并列举了几种常见的IPC方式。接着深入探讨了管道通信,包括无名管道(匿名管道)和有名管道(命名管道)。无名管道主要用于父子进程间的单向通信,有名管道则可用于任意进程间的通信。文中提供了丰富的示例代码,展示了如何使用`pipe()`和`mkfifo()`函数创建管道,并通过实例演示了如何利用管道进行进程间的消息传递。此外,还分析了管道的特点、优缺点以及如何通过`errno`判断管道是否存在,帮助读者更好地理解和应用管道通信技术。
|
2月前
|
SQL 网络协议 数据库连接
已解决:连接SqlServer出现 provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程【C#连接SqlServer踩坑记录】
本文介绍了解决连接SqlServer时出现“provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程”错误的步骤,包括更改服务器验证模式、修改sa用户设置、启用TCP/IP协议,以及检查数据库连接语句中的实例名是否正确。此外,还解释了实例名mssqlserver和sqlserver之间的区别,包括它们在默认设置、功能和用途上的差异。
|
3月前
|
消息中间件 Linux 开发者
Linux进程间通信秘籍:管道、消息队列、信号量,一文让你彻底解锁!
【8月更文挑战第25天】本文概述了Linux系统中常用的五种进程间通信(IPC)模式:管道、消息队列、信号量、共享内存与套接字。通过示例代码展示了每种模式的应用场景。了解这些IPC机制及其特点有助于开发者根据具体需求选择合适的通信方式,促进多进程间的高效协作。
166 3
|
3月前
|
Linux
Linux源码阅读笔记13-进程通信组件中
Linux源码阅读笔记13-进程通信组件中
|
3月前
|
消息中间件 安全 Java
Linux源码阅读笔记13-进程通信组件上
Linux源码阅读笔记13-进程通信组件上
|
3月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
71 0