// Create a child process that uses the previously created pipes for STDIN and STDOUT.
void CreateChildProcess()
{
TCHAR szCmdline[] = TEXT("child");
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bSuccess = FALSE;
// Set up members of the STARTUPINFO structure.
// This structure specifies the STDIN and STDOUT handles for redirection.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); // Set up members of the PROCESS_INFORMATION structure.
// Create the child process.
bSuccess = CreateProcess(NULL,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if ( ! bSuccess ) ErrorExit(TEXT("CreateProcess")); // If an error occurs, exit the application.
// Close handles to the child process and its primary thread.
// Some applications might keep these handles to monitor the status
// of the child process, for example.
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
}
HANDLE g_hInputFile = NULL;
#define BUFSIZE 4096
// Read from a file and write its contents to the pipe for the child's STDIN.
// Stop when there is no more data.
void WriteToPipe(void)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
BOOL bSuccess = FALSE;
for (;;)
{
bSuccess = ReadFile(g_hInputFile, chBuf, BUFSIZE, &dwRead, NULL);
if ( ! bSuccess || dwRead == 0 ) break;
// Close the pipe handle so the child process stops reading.
if ( ! CloseHandle(g_hChildStd_IN_Wr) ) ErrorExit(TEXT("StdInWr CloseHandle"));
}
// Read output from the child process's pipe for STDOUT
// and write to the parent process's pipe for STDOUT.
// Stop when there is no more data.
void ReadFromPipe(void)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
BOOL bSuccess = FALSE;
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// The pipe is assumed to have enough buffer space to hold the
// data the child process has already written to it.
for (;;) {
bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
if ( ! bSuccess || dwRead == 0 ) break;
if ( ! CloseHandle(g_hChildStd_OUT_Rd) ) ErrorExit(TEXT("StdOutRd CloseHandle"));
}
int _tmain(int argc, TCHAR *argv[])
{
// <
if (argc == 1) ErrorExit(TEXT("Please specify an input file.\n"));
SECURITY_ATTRIBUTES saAttr;
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDIN.
if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) ErrorExit(TEXT("Stdin CreatePipe"));
// Ensure the write handle to the pipe for STDIN is not inherited.
if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) ErrorExit(TEXT("Stdin SetHandleInformation"));
// Create a pipe for the child process's STDOUT.
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) ) ErrorExit(TEXT("StdoutRd CreatePipe"));
// Ensure the read handle to the pipe for STDOUT is not inherited.
if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ) ErrorExit(TEXT("Stdout SetHandleInformation"));
CreateChildProcess(); // Create the child process.
if (!CloseHandle(g_hChildStd_IN_Rd)) ErrorExit(TEXT("StdInRd CloseHandle"));
if (!CloseHandle(g_hChildStd_OUT_Wr)) ErrorExit(TEXT("StdOutWr CloseHandle"));
// Get a handle to an input file for the parent.
// This example assumes a plain text file and uses string output to verify data flow.
g_hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if ( g_hInputFile == INVALID_HANDLE_VALUE ) ErrorExit(TEXT("CreateFile"));
// Write to the pipe that is the standard input for a child process.
// Data is written to the pipe's buffers, so it is not necessary to wait
// until the child process is running before writing data.
WriteToPipe();
// Read from pipe that is the standard output for child process.
ReadFromPipe();
// >
return 0;
}
명명된 파이프
The named pipe instance is a global resource
CreateNamedPipe()
PIPE_ACCESS_DUPLEX
PIPE_TYPE_BYTE
CloseHandle()
ConnectNamedPipe() // blocking, listen? // indicating that there is an available named pipe instance
ERROR_PIPE_CONNECTED
DisconnectNamedPipe() // for connection with another client
ReadFile()
WriteFile()
CreateFile()
ERROR_PIPE_BUSY
OPEN_EXISTING
WaitNamedPipe() // blocking??, connect?
ConnectNamedPipe()
NMPWAIT_WAIT_FOREVER
Nonetheless, the client's CreateFile call could fail if some other client opens the named pipe instance or if the server closes the instance's handle.
CloseHandle()
allowing another client to connect on the same named pipe instance