进程间通信(4) 匿名管道

  • 匿名管道没有名称,所以只能在父进程中调用CreateProcess函数创建子进程时,将管道的读、写句柄传递给子进程。
  • 匿名管道只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。

1. 过程:

  • a. createpipe得到hWrite和hRead两句柄
  • b. 将hWrite和hRead通过createprocess传递给子进程
  • c. 子进程通过GetStdHandle获取 hWrite和hRead
  • d. 你读我写

2. api详细说明

read:

	char buf[100];
	DWORD dwRead;
	if(!ReadFile(hRead,buf,100,&dwRead,NULL))

write:

	char buf[]="匿名管道测试程序";
	DWORD dwWrite;
	if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)) 
BOOL CreatePipe(
  PHANDLE               hReadPipe,
  PHANDLE               hWritePipe,
  LPSECURITY_ATTRIBUTES lpPipeAttributes,
  DWORD                 nSize
);

typedef struct _SECURITY_ATTRIBUTES {
  DWORD  nLength;
  LPVOID lpSecurityDescriptor;
  BOOL   bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
BOOL WINAPI CreateProcess(
  _In_opt_    LPCTSTR               lpApplicationName,
  _Inout_opt_ LPTSTR                lpCommandLine,
  _In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_        BOOL                  bInheritHandles,
  _In_        DWORD                 dwCreationFlags,
  _In_opt_    LPVOID                lpEnvironment,
  _In_opt_    LPCTSTR               lpCurrentDirectory,
  _In_        LPSTARTUPINFO         lpStartupInfo,
  _Out_       LPPROCESS_INFORMATION lpProcessInformation
);
  • lpApplicationName
    指定某路径下exe,若路径包括空格,则语义改变。

  • lpCommandLine
    参数,也可将lpApplicationName设为Null,此lpCommandLine指定name,
    eg.
    “c:\program fileslsub dir\program name”=>
    c:lprogram.exe fileslsub dirlprogram name

Windows将按照如下顺序寻找这个可执行文件:
  1.当前应用程序的目录。
  2.父进程的目录。
  3. Windows 95:Windows系统目录,可以使用 GetSystemDirectory函数获得。
   Windows NT:32位Windows系统目录。可以使用GetSystemDirectory函数获得,目录名是SYSTEM32。
  4. 在Windows NT中:16位Windows系统目录。不可以使用Win32函数获得这个目录,但是它会被搜索,目录名是SYSTEM。
  5.Windows目录。可以使用 GetWindowsDirectory函数获得这个目录。
  6.列在PATH环境变量中的目录。

  • bInheritHandles
    子进程是否从父进程继承句柄

  • dwCreationFlags

值:DEBUG_PROCESS
如果这个标志被设置,调用进程将被当作一个调试程序,并且新进程会被当作被调试的进程。系统把被调试程序发生的所有调试事件通知给调试器。如果你使用这个标志创建进程,只有调用进程(调用CreateProcess函数的进程)可以调用WaitForDebugEvent函数。

值:DEBUG_ONLY_THIS_PROCESS
含义:如果此标志没有被设置且调用进程正在被调试,新进程将成为调试调用进程的调试器的另一个调试对象。如果调用进程没有被调试,有关调试的行为就不会产生。

值:DETACHED_PROCESS
含义:对于控制台进程,新进程没有访问父进程控制台的权限。新进程可以通过AllocConsole函数自己创建一个新的控制台。这个标志不可以与CREATE_NEW_CONSOLE标志一起使用。

还可表示进程优先级进程间通信(4)  匿名管道

  • lpStartupInfo
typedef struct _STARTUPINFO 
{ 
DWORD cb;
LPTSTR lpReserved;  
LPTSTR lpDesktop; 
LPTSTR lpTitle;  
DWORD dwX;  
DWORD dwY;  
DWORD dwXSize;
DWORD dwYSize;  
DWORD dwXCountChars;  
DWORD dwYCountChars;  
DWORD dwFillAttribute;  
DWORD dwFlags;  
WORD wShowWindow;  
WORD cbReserved2;  
LPBYTE lpReserved2;  
HANDLE hStdInput;  
HANDLE hStdOutput;  
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;

用于决定新进程的主窗体如何显示的STARTUPINFO结构体
进程间通信(4)  匿名管道

  • LPPROCESS_INFORMATION lpProcessInformation
    子进程的句柄数据
typedef struct _PROCESS_INFORMATION { 
  HANDLE hProcess; 
  HANDLE hThread; 
  DWORD dwProcessId; 
  DWORD dwThreadId; 
} PROCESS_INFORMATION; 

dwProcessId,dwThreadId需要程序员手动CloseHandle

在创建一个新进程时,系统会为该进程建立一个进程内核对象和一个线程内核对象,而内核对象都有一个使用计数,系统会为这两个对象赋予初始的使用计数:1,当CreateProcess 函数在其内部打开这些对象时,每个对象的使用计数就变为2

【引用】

  1. 代码 https://github.com/thefistlei/os/tree/main/processCommunication/anonymousPipe
  2. VC++ 深入详解 孙鑫
  3. CreatePipe function (namedpipeapi.h)https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
上一篇:python学习笔记(§ 1.1)转自CSDN,知乎


下一篇:基于C语言的java串口通信程序