- UID
- 1029342
- 性别
- 男
|
匿名管道的使用
匿名管道主要用于本地父进程和子进程之间的通信,
在父进程中的话,首先是要创建一个匿名管道,
在创建匿名管道成功后,可以获取到对这个匿名管道的读写句柄,
然后父进程就可以向这个匿名管道中写入数据和读取数据了,
但是如果要实现的是父子进程通信的话,那么还必须在父进程中创建一个子进程,
同时,这个子进程必须能够继承和使用父进程的一些公开的句柄,
为什么呢?
因为在子进程中必须要使用父进程创建的匿名管道的读写句柄,
通过这个匿名管道才能实现父子进程的通信,所以必须继承父进程的公开句柄。
同时在创建子进程的时候,
必须将子进程的标准输入句柄设置为父进程中创建匿名管道时得到的读管道句柄,
将子进程的标准输出句柄设置为父进程中创建匿名管道时得到的写管道句柄。
然后在子进程就可以读写匿名管道了。
匿名管道的创建
BOOL WINAPI CreatePipe( __out PHANDLE hReadPipe, __out PHANDLE hWritePipe, __in LPSECURITY_ATTRIBUTES lpPipeAttributes, __in DWORD nSize );参数 hReadPipe 为输出参数,该句柄代表管道的读取句柄。
参数 hWritePipe 为输出参数,该句柄代表管道的写入句柄。
参数 lpPipeAttributes 为一个输入参数,指向一个 SECURITY_ATTRIBUTES 的结构体指针,
其检测返回的句柄是否能够被子进程继承,如果此参数为 NULL ,则表明句柄不能被继承,
在匿名管道中,由于匿名管道要在父子进程之间进行通信,
而子进程如果想要获得匿名管道的读写句柄,则其只能通过从父进程继承获得,
当一个子进程从其父进程处继承了匿名管道的读写句柄以后,
子进程和父进程之间就可以通过这个匿名管道的读写句柄进行通信了。
所以在这里必须构建一个 SECURITY_ATTRIBUTES 的结构体,
并且该结构体的第三个结构成员变量 bInheritHandle 参数必须设置为 TRUE ,
从而让子进程可以继承父进程所创建的匿名管道的读写句柄。
typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
参数 nSize 用来指定缓冲区的大小,
如果此参数设置为 0 ,则表明系统将使用默认的缓冲区大小。一般将该参数设置为 0 即可。
子进程的创建
BOOL CreateProcess( LPCWSTR pszImageName, LPCWSTR pszCmdLine, LPSECURITY_ATTRIBUTES psaProcess, LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles, DWORD fdwCreate, LPVOID pvEnvironment, LPWSTR pszCurDir, LPSTARTUPINFOW psiStartInfo, LPPROCESS_INFORMATION pProcInfo);参数 pszImageName 是一个指向 NULL 终止的字符串,用来指定可执行程序的名称。
参数 pszCmdLine 用来指定传递给新进程的命令行字符串,一般做法是在 pszImageName 中传递可执行文件的名称,
在 pszCmdLine 中传递命令行参数。
参数 psaProcess 即代表当 CreateProcess 函数创建进程时,需要给进程对象设置一个安全性。
参数 psaThread 代表当 CreateProcess 函数创建新进程后,需要给该进程的主线程对象设置一个安全性。
参数 fInheritHandles 用来指定父进程随后创建的子进程是否能够继承父进程的对象句柄,
如果该参数设置为 TRUE ,则父进程的每一个可继承的打开句柄都将被子进程所继承,
继承的句柄与原始的句柄拥有同样的访问权。
在匿名管道的使用中,因为子进程需要使用父进程中创建的匿名管道的读写句柄,
所以应该将这个参数设置为 TRUE ,从而可以让子进程继承父进程创建的匿名管道的读写句柄。
参数 fdwCreate 用来指定控件优先级类和进程创建的附加标记。
如果只是为了启动子进程,则并不需要设置它创建的标记,可以将此参数设置为 0,
对于这个参数的具体取值列表可以参考 MSDN 。
参数 pvEnvironment 代表指向环境块的指针,
如果该参数设置为 NULL ,则默认将使用父进程的环境。通常给该参数传递 NULL。
参数 pszCurDir 用来指定子进程当前的路径,
这个字符串必须是一个完整的路径名,其包括驱动器的标识符,
如果此参数设置为 NULL ,那么新的子进程将与父进程拥有相同的驱动器和目录。
参数 psiStartInfo 指向一个 StartUpInfo 的结构体的指针,用来指定新进程的主窗口如何显示。
typedef struct _STARTUPINFOA { DWORD cb; LPSTR lpReserved; LPSTR lpDesktop; LPSTR 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; } STARTUPINFOA, *LPSTARTUPINFOA;
对于 dwFlags 参数来说,如果其设置为 STARTF_USESTDHANDLES ,
则将会使用该 STARTUPINFO 结构体中的 hStdInput , hStdOutput , hStdError 成员,
来设置新创建的进程的标准输入,标准输出,标准错误句柄。
参数 pProcInfo 为一个输出参数,
指向一个 PROCESS_INFORMATION 结构体的指针,用来接收关于新进程的标识信息。
typedef struct _PROCESS_INFORMATION { HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; }PROCESS_INFORMATION;
其中 hProcess 和 hThread 分别用来标识新创建的进程句柄和新创建的进程的主线程句柄。
dwProcessId 和 dwThreadId 分别是全局进程标识符和全局线程标识符。
前者可以用来标识一个进程,后者用来标识一个线程。 |
|