Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

윈도 익명 파이프

리눅스의 익명 파이프와 동일한 특성을 가지며, 사용방법 역시 유사하다. 즉
  • 부모 프로세스와 자식 프로세스간의 통신
  • 읽기전용과 쓰기전용의 두개의 파이프로 전 이중 통신의 구현
  • 다른 프로세스는 참조할 수 없음.(참조할 이름이 없기 때문에)

createpipe로 익명 파이프 생성

리눅스에 pipe(2)가 있다면 윈도는 CreatePipe(:4200)함수로 파이프를 만든다.
BOOL WINAPI CreatePipe(
  __out     PHANDLE hReadPipe,
  __out     PHANDLE hWritePipe,
  __in_opt  LPSECURITY_ATTRIBUTES lpPipeAttributes,
  __in      DWORD nSize
);
pipe와 마찬가지로 읽기전용 (hReadPipe)와 쓰기전용 (hWritePipe)의 두개의 파이프를 만든다. nSize는 버퍼의 크기로 0을 입력하면 기본 버퍼 크기를 사용한다. 일반적으로 0을 사용하면 된다. 성공하면 0이 아닌 값을 리턴하고, 실패하면 0을 리턴한다.

통신은 ReadFile(:12)과 WriteFile(:12)를 이용한다.

리눅스 파이프와의 차이점

파이프의 근본적인 특징은 동일하지만, 프로세스에서의 차이가 있다. 리눅스(:12)에서 자식 프로세스는 fork(:2)함수로 부모프로세스를 복사해서 만들어진다. 반면 윈도에서 프로세스를 만들기 위해서 사용하는 CreateProcess(:4200)함수는 부모프로세스를 복사하는게 아닌 외부 프로세스를 새로 생성하는 방식으로 작동한다. 즉 리눅스의 fork&exec를 함께 사용한 것과 비슷하게 작동한다고 볼 수 있다.

리눅스로 윈도 파이프를 구현을 의사코드로 나타내 보았다.
int pd[2];
pid = fork();
pipe(pd); // 파이프를 만든다.

if(pid == 0) // 자식 프로세스
{
    dup2(dup[0], 1);  // 읽기 전용 파이프를 표준출력(:12)으로 복사한다. 
    dup2(dup[1], 0);  // 쓰기 전용 파이프를 표준입력(:12)으로 복사한다.

    // 프로그램을 실행한다.
    // 실행된 프로그램의 표준입력과 표준출력은 각각 쓰기전용 파이프와 읽기 전용 파이프로 연결되어있다. 
    // 표준입력과 표준출력으로 파이프 통신을 하면 된다.
    execl("Program");
}
else (pid > 0) // 부모 프로세스
{
   // 파이프로 통신한다.
   read(pd[0]);
   write(pd[1]);
}

예제 프로그램

echo 서버, 클라이언트 프로그램을 만들기로 했다. 서버 프로그램의 이름은 echo_server.c, 클라이언트 프로그램의 이름은 echo_cli.c 이다.

예제 : echo_server.c
#include <stdio.h>
#include <stdio.h>
#include <windows.h>
#include <tchar.h>

#define MAX_LINE 1024
int main(int argc, char **argv)
{
	HANDLE readPipe, writePipe;
	SECURITY_ATTRIBUTES sec;
	int writen;
	int rtv;
	TCHAR command[80] = {0,};
	char buf[MAX_LINE];
	STARTUPINFO si = {0,};
	PROCESS_INFORMATION pi;

	sec.nLength = sizeof(SECURITY_ATTRIBUTES);
	sec.bInheritHandle = TRUE;
	sec.lpSecurityDescriptor = NULL;

	CreatePipe(&readPipe, &writePipe, &sec, 0);

	_stprintf(command, _T("C:\\pipe_cli.exe %d"), (HANDLE)readPipe);

	printf("command : %s\n", command);
	si.cb = sizeof(si);
	rtv = CreateProcess(
		NULL, command,
		NULL, NULL,
		TRUE,
		CREATE_NEW_CONSOLE,
		NULL, NULL,
		&si, &amp;pi);
	if (!rtv)
	{
		printf("Error %d\n", GetLastError());
		return 1;
	}


	while(1)
	{
		printf("> ");
		fgets(buf, MAX_LINE, stdin);
		if(strncmp(buf, "quit\n", 5)==0) break;
		WriteFile(writePipe, buf, strlen(buf), &writen, NULL);
	}
	CloseHandle(readPipe);
	CloseHandle(writePipe);
}

예제 : echo_cli.c
#include <stdio.h>
#include <windows.h>

#define MAX_LINE 1024
int main(int argc, char **argv)
{
	HANDLE readPipe = (HANDLE)(atoi(argv[1]));
	int readn;
	char buf[MAX_LINE];

	while(1)
	{
		memset(buf, 0x00, MAX_LINE);
		ReadFile (
			readPipe, 
			buf, 
			MAX_LINE, 
			&readn, 
			NULL
			);
		printf(" --> %s", buf);
	}
}