Pipes : Introduction to pipes
What is IPC?
$ ls -1 | cut -d'.' -f1 | uniq | sort | tee dir_contents
위 코드는 어떤 일을 할까요? ls는 현재 디렉토리 정보를 나타냅니다(-l은 결과를 줄로 보여달라는 의미입니다). 다음 cut 명령어는 .부분을 잘라냅니다. 다음 unique는 모든 라인이 중복되지 않고 하나만 존재하도록 하고, sort는 정렬을 시켜주고 tee는 파일로 아웃풋을 보내줍니다.
위 과정에서 중요한 점은 bash가 5개의 분리된 프로세스를 생성해 아래와 같이 프로세스들의 standard out과 in을 연결했다는 것입니다.
(0) ls (1)------>(0) cut (1)------->(0) uniq (1)------>(0) sort (1)------>(0) tee (1)
파이프의 숫자는 각각의 프로세스의 file descriptor입니다. 화살표는 redirect 또는 파이프의 output이 가는 곳을 의미합니다.
What is pipe?
POSIX의 파이프는 실제 파이프와 거의 같습니다. 한 쪽 끝에서 바이트를 채우면 다른 쪽에서도 같은 순서로 나타날 것입니다. 실제 파이프와는 다르게, 항상 한쪽 방향으로만 흐름이 생겨 한 파일 디스크립터는 오직 읽는데만 사용되고 다른 하나는 쓰기에 사용됩니다. pipe의 system call을 pipe를 만드는 데 사용됩니다.
int filedes[2]; pipe (filedes); printf("read from %d, write to %d\n", filedes[0], filedes[1]);
이러한 file descriptor는 read와 사용되어질 수 있습니다.
// To read... char buffer[80]; int bytesread = read(filedes[0], buffer, sizeof(buffer));
또는, 아래와 같이 child process에서 write를 통해 부모에게 메세지를 보내는데 사용되어 질 수도 있습니다.
if (child == 0) { write(filedes[1], "done", 4); }
Can I use pipe inside a single process?
#include <unistd.h> #include <stdlib.h> #include <stdio.h> int main() { int fh[2]; pipe(fh); FILE *reader = fdopen(fh[0], "r"); FILE *writer = fdopen(fh[1], "w"); // Hurrah now I can use printf rather than using low-level read() write() printf("Writing...\n"); fprintf(writer,"%d %d %d\n", 10, 20, 30); fflush(writer); printf("Reading...\n"); int results[3]; int ok = fscanf(reader,"%d %d %d", results, results + 1, results + 2); printf("%d values parsed: %d %d %d\n", ok, results[0], results[1], results[2]); return 0; }
이러한 방식으로 파이프를 사용하는 방법의 문제는 파이프의 버퍼가 제한된 경우에 파이프에 쓰는 것이 블록을 일크킬 수 있다는 것입니다. 만약 파이프가 쓰기로 가득 차면 프로세스는 블록될 것입니다. 버퍼의 최대 크기는 시스템에 의존적이지만, 일반적으로 4KB에서 128KB까지입니다.
int main() { int fh[2]; pipe(fh); int b = 0; #define MESG "..............................." while(1) { printf("%d\n",b); write(fh[1], MESG, sizeof(MESG)) b+=sizeof(MESG); } return 0; }