进程间通信-匿名管道

注意:匿名管道只能在父进程和子进程之间进行,所以必须由父进程通过CreateProcess来创建子进程才能形成父子关系.否则,不能形成父子进程关系.

 

CreatePipe 创建一个匿名管道,返回管道的读句柄,写句柄.

BOOL CreatePipe(
  PHANDLE hReadPipe,
  PHANDLE hWritePipe,
  LPSECURITY_ATTRIBUTES lpPipeAttributes,
  DWORD nSize
);
前两个参数为管道的读句柄和写句柄

第三个参数是指向SECURITY_ATTRIBUTES指针,检测返回的句柄是否可以为子进程所继承,如果这个参数是NULL,这个句柄不能够被继承.在其他大多函数中,涉及到SECURITY_ATTRIBUTES一般都默认设置成NULL,让系统设置默认的安全描述符,得到的句柄不能够被子进程所继承.但这里不能设置成NULL,因为对于匿名管道这能在父子进程之间进行通信,对于子进程如果想得到匿名管道句柄,只能从父管道继承而来,当一个子进程从父进程继承管道的读写句柄,就能和父进程通信了.

最后一个参数设置管道的缓冲区大小,0为缺省,系统提供默认值.

这里

typedef struct _SECURITY_ATTRIBUTES {
  DWORD nLength;
  LPVOID lpSecurityDescriptor;
  BOOL bInheritHandle;
} SECURITY_ATTRIBUTES,
*PSECURITY_ATTRIBUTES;
第一个参数为结构提的长度,为sizeof(SECURITY_ATTRIBUTES).

第二个成员是安全描述符,这里设置成NULL,让系统自动设置,但不能整个结构设置为NULL,那样第三个变量也会设置成NULL,

第三个成员为真,则可以被子进程所继承.

 

Createprocess创建一个进程

BOOL CreateProcess(
  LPCTSTR lpApplicationName,
  LPTSTR lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,//设置安全属性
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL bInheritHandles,//是否可以继承句柄
  DWORD dwCreationFlags,//控制优先级的附加标记
  LPVOID lpEnvironment,
  LPCTSTR lpCurrentDirectory,
  LPSTARTUPINFO lpStartupInfo,//指定新的窗口如何实现
  LPPROCESS_INFORMATION lpProcessInformation
);
 

上面函数可以用第一个参数传递一个可执行模块的名字,如果用它来加载可执行的模块名,而没有相对路径,程序会在当前文件目录下查找,而不会到系统路径下查找要执行的模块.如果找不到就以失败返回.同时,它不会给可执行模块自动添加扩展名.

 

第二个参数来传递可执行模块的参数.

也可以用它来添加可执行模块,它在当前目录查找不到会到系统路径去查找,同时如果没有写可执行模块的扩展名,它会自动扩展可执行文件的扩展名.通常同时用它来传递可执行模块名,和参数.

 

 

代码片段:

创建管道

定义类成员变量:

HANDLE hWrite;

HANDLE hRead;

构造函数初始化这两个句柄

CParentView::CParentView()

{

       // TODO: add construction code here

       hRead=NULL;

       hWrite=NULL;

}

析构函数

CParentView::~CParentView()

{

       if(hRead)

              CloseHandle(hRead);

       if(hWrite)

              CloseHandle(hWrite);

}

 

void CParentView::OnPipeCreate()

{

       SECURITY_ATTRIBUTES sa;

       sa.bInheritHandle=TRUE;

       sa.lpSecurityDescriptor=NULL;

       sa.nLength=sizeof(SECURITY_ATTRIBUTES);

       if(!CreatePipe(&hRead,&hWrite,&sa,0))

       {

              MessageBox("创建匿名管道失败!");

              return;

       }

       STARTUPINFO sui;

       PROCESS_INFORMATION pi;//进程信息结构体指针

/*

将结构提中的所有成员都设置成0

*/

       ZeroMemory(&sui,sizeof(STARTUPINFO));

       sui.cb=sizeof(STARTUPINFO);

       sui.dwFlags=STARTF_USESTDHANDLES;

       sui.hStdInput=hRead;

       sui.hStdOutput=hWrite;

//得到标准错误句柄

       sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);

      

       if(!CreateProcess("..//Child//Debug//Child.exe",NULL,NULL,NULL,

                     TRUE,0,NULL,NULL,&sui,&pi))

       {

              CloseHandle(hRead);

              CloseHandle(hWrite);

//下面把hRead,hWrite设置成NULL,防止析构函数再次把这两个句柄关闭

              hRead=NULL;

              hWrite=NULL;

              MessageBox("创建子进程失败!");

              return;

       }

       else

       {

              CloseHandle(pi.hProcess);

              CloseHandle(pi.hThread);

       }

}

 

从匿名管道读取数据,和写入数据

用ReadFile 和 WriteFile 来向管道中写入数据和读取数据

void CParentView::OnPipeRead()                        

{

       // TODO: Add your command handler code here

       char buf[100];

       DWORD dwRead;

       if(!ReadFile(hRead,buf,100,&dwRead,NULL))

       {

              MessageBox("读取数据失败!");

              return;

       }

       MessageBox(buf);

}

 

void CParentView::OnPipeWrite()

{

       // TODO: Add your command handler code here

       char buf[]="http://www.sunxin.org";

       DWORD dwWrite;

       if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))

       {

              MessageBox("写入数据失败!");

              return;

       }

}

 

子进程读取数据和写入数据

同样创建成员变量

HANDLE hWrite;

HANDLE hRead;

 

CParentView::CParentView()

{

       hRead=NULL;

       hWrite=NULL;

}

 

CParentView::~CParentView()

{

       if(hRead)

              CloseHandle(hRead);

       if(hWrite)

              CloseHandle(hWrite);

}

OnInitialUpdate()是窗口创建完成之后第一个调用的函数

void CChildView::OnInitialUpdate()

{

       CView::OnInitialUpdate();     

//到子进程的标准输入和标准输出句柄

       hRead=GetStdHandle(STD_INPUT_HANDLE);

       hWrite=GetStdHandle(STD_OUTPUT_HANDLE);

}

 

 

void CChildView::OnPipeRead()

{

       char buf[100];

       DWORD dwRead;

       if(!ReadFile(hRead,buf,100,&dwRead,NULL))

       {

              MessageBox("读取数据失败!");

              return;

       }

       MessageBox(buf);

}

 

void CChildView::OnPipeWrite()

{

       char buf[]="匿名管道测试程序";

       DWORD dwWrite;

       if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))

       {

              MessageBox("写入数据失败!");

              return;

       }

}

 

你可能感兴趣的:(command,Security,null,扩展,attributes,construction)