标签:
操作系统的实验要用到管道.
管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。
匿名管道实施细则
匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:
BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针
PHANDLE hWritePipe, // 指向写句柄的指针
LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针
DWORD nSize // 管道大小
);
通过hReadPipe和hWritePipe所指向的句柄可分别以只读、只写的方式去访问管道。
匿名管道并不支持异步读、写操作,这也就意味着不能在匿名管道中使用ReadFileEx()和WriteFileEx(),而且ReadFile()和WriteFile()中的lpOverLapped参数也将被忽略。匿名管道将在读、写句柄都被关闭后退出,也可以在进程中调用CloseHandle()函数来关闭此句柄。
1.如果只想得到子进程的结果则可以只创建一个管道,然后ReadFile()得到输出就行了。 如下: STARTUPINFO si;
PROCESS_INFORMATION pi;
char ReadBuf[100];
DWORD ReadNum;
HANDLE hRead; // 管道读句柄
HANDLE hWrite; // 管道写句柄
BOOL bRet = CreatePipe(&hRead, &hWrite, NULL, 0); // 创建匿名管道
if (bRet == TRUE)
printf("成功创建匿名管道!\n");
else
printf("创建匿名管道失败,错误代码:%d\n", GetLastError());
// 得到本进程的当前标准输出
HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);
// 设置标准输出到匿名管道
SetStdHandle(STD_OUTPUT_HANDLE, hWrite);
GetStartupInfo(&si); // 获取本进程的STARTUPINFO结构信息
bRet = CreateProcess(NULL, "Client.exe", NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi); // 创建子进程
SetStdHandle(STD_OUTPUT_HANDLE, hTemp); // 恢复本进程的标准输出
if (bRet == TRUE) // 输入信息
printf("成功创建子进程!\n");
else
printf("创建子进程失败,错误代码:%d\n", GetLastError());
CloseHandle(hWrite); // 关闭写句柄
// 读管道直至管道关闭
while (ReadFile(hRead, ReadBuf, 100, &ReadNum, NULL))
{
ReadBuf[ReadNum] = ‘\0‘;
printf("从管道[%s]读取%d字节数据\n", ReadBuf, ReadNum);
}
if (GetLastError() == ERROR_BROKEN_PIPE) // 输出信息
printf("管道被子进程关闭\n");
else
printf("读数据错误,错误代码:%d\n", GetLastError());
2.如果要想向子进程输入数据则要为子进程的标准输入也创建一个管道.再用WriteFile()输入。 #include "Windows.h" #include "stdio.h" void main() { SECURITY_ATTRIBUTES sa,sa2; HANDLE hInputRead,hInputWrite; HANDLE hOutputRead,hOutputWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; if (!CreatePipe(&hOutputRead,&hOutputWrite,&sa,0)) { printf("Error On CreatePipe1"); return; } sa2.nLength = sizeof(SECURITY_ATTRIBUTES); sa2.lpSecurityDescriptor = NULL;
sa2.bInheritHandle = TRUE; if (!CreatePipe(&hInputRead,&hInputWrite,&sa2,0)) { printf("Error On CreatePipe2"); return; }
STARTUPINFO si; PROCESS_INFORMATION pi; si.cb = sizeof(STARTUPINFO); GetStartupInfo(&si); si.hStdError = hOutputWrite; /// si.hStdOutput = hOutputWrite; ///写句柄赋予标准输出(或标准错误)句柄 si.hStdInput = hInputRead; /// //当父进程向子进程发送数据时,用SetStdHandle() //将管道的读句柄赋予标准输入句柄;在从子进程接收数据时, //则用SetStdHandle()将管道的写句柄赋予标准输出(或标准错误)句柄。 //然后,父进程可以调用进程创建函数CreateProcess()生成子进程。 // 如果父进程要发送数据到子进程,父进程可调用WriteFile() // 将数据写入到管道(传递管道写句柄给函数),子进程则调用GetStdHandle() // 取得管道的读句柄,将该句柄传入ReadFile()后从管道读取数据。
si.wShowWindow = SW_HIDE; si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; DWORD dwWritten; if (!CreateProcess(NULL,"c:\\windows\\system32\\cmd.exe ",NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) { printf("Error On CreateProcess"); return; }
CloseHandle(hInputRead); CloseHandle(hOutputWrite); char szInPut[20] = "dir\r\n "; // 父进程向子进程发送数据,输入 WriteFile(hInputWrite, szInPut, strlen(szInPut), &dwWritten, NULL); char buffer[4096] = {0}; DWORD bytesRead; // 父进程向子进程得到数据,输出 while (true) {
if(ReadFile(hOutputRead,buffer,4095,&bytesRead,NULL) == NULL)
{ break; } printf(buffer);
Sleep(500); }
CloseHandle(hInputWrite); CloseHandle(hOutputRead);}
c++里面执行一个exe文件,匿名管道
标签:
原文地址:http://www.cnblogs.com/shouce/p/5252674.html