[제12장] 프로세스 간 통신 : 파이프
=================================================================
* Subject : [제12장] 프로세스 간 통신 : 파이프
* Writer: w0rm9 (research.hackerschool.org)
* Date: 2004/02/15
=================================================================
/* 스터디 내용을 중심으로 정리했고, 소스는 몽이님이 사용했던 소스 및 수정한 소스를 사용했습니다.
*/
0x01. 프로세스 파이프
■ popen
사용법)
#include <stdio.h>
FILE *popen(const char *command, const char *open_mode);
int pclose(FILE *stream_to_close);
=> command는 실행할 프로그램 이름이며, open_mode는 "r"과 "w"중 하나이다.
pclose()함수는 프로세스가 끝날 때까지 대기한다.
테스트)
[w0rm9@work PIPE]$ cat popen1.c
#include <stdio.h>
int main()
{
FILE *fp;
char string[256];
fp = popen("/bin/ls", "r"); // "/bin/ls"를 "r"모드로 실행. 즉, /bin/ls 의 출력 결과를 읽어들인다.
while(fread(string, 1, 256, fp)) // 읽어들인 결과를 string으로 읽어와서
printf("%s", string); // 출력
pclose(fp);
}
[w0rm9@work PIPE]$ gcc -o popen1 popen1.c
[w0rm9@work PIPE]$ ./popen1
popen1
popen1.c
popen2
popen2.c
[w0rm9@work PIPE]$ cat popen2.c
#include <stdio.h>
int main()
{
FILE *fp;
char buf[256];
sprintf(buf, "사랑해\n");
fp = popen("/bin/cat > text", "w"); // "/bin/cat > text"를 "w"모드로 실행. /bin/cat > text 에 무언가를 보낸다.
if(fp != NULL){
fwrite(buf, sizeof(char), strlen(buf), fp); // buf의 내용을 /bin/cat > text에 쓴다.
pclose(fp);
}
}
[w0rm9@work PIPE]$ gcc -o popen2 popen2.c
[w0rm9@work PIPE]$ ./popen2
[w0rm9@work PIPE]$ ls -al text
-rw-rw-r-- 1 w0rm9 w0rm9 7 2월 16 10:43 text
[w0rm9@work PIPE]$ cat text
사랑해
0x02. 파이프 호출
■ pipe
사용법)
#include <unistd.h>
int pipe(int file_descriptor[2]);
=> file_descriptor[1]에는 데이터 저장, file_descriptor[0]에는 데이터 읽기
테스트)
[w0rm9@work PIPE]$ cat pipe.c
#include <stdio.h>
#include <unistd.h>
int main()
{
int pipes[2];
char buffer[1024], string[1024];
pipe(pipes); // 1. pipe()호출
if(fork() ==0){
sleep(3);
read(pipes[0], buffer, sizeof(buffer)); // 4. pipes[0]를 buffer가 읽어온다.
printf("자식 : %s\n", buffer); // 5. 읽은 buffer내용을 출력한다.
}
else{
printf("부모 : ");
fgets(string, 1024, stdin); // 2. string에 표준입력한다.
write(pipes[1], string, strlen(string)); // 3. string의 내용을 pipes[1]에 쓴다.
sleep(3);
}
}
[w0rm9@work PIPE]$ gcc -o pipe pipe.c
[w0rm9@work PIPE]$ ./pipe
부모 : 사랑해^^
자식 : 사랑해^^
■ dup, dup2
사용법)
#include <unistd.h>
int dup(int file_descriptor);
int dup2(int file_descriptor_one, int file_descriptor_one);
=> dup()는 새로운 파일 기술자를 연다. 가장 낮은 유효한 값을 사용하여 반환
dup2()는 새로운 파일 기술자를 지정하여 반환할 수 있다.
테스트)
[w0rm9@work PIPE]$ cat dup.c
#include <stdio.h>
#include <fcntl.h>
int main()
{
int a, b, c;
a = open("/etc/passwd", O_RDONLY);
b = dup(a);
c = dup2(a, 100);
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
close(a);
close(b);
}
[w0rm9@work PIPE]$ gcc -o dup dup.c
[w0rm9@work PIPE]$ ./dup
a = 3 // open()의한 파일기술자 3
b = 4 // 0은 표준입력, 1은 표준출력, 2은 표준에러, open()의한 파일기술자 3, 가장 낮은 유효한 값은 4
c = 100 // 직접 지정해준 파일기술자 100
[w0rm9@work PIPE]$ cat dup2.c
#include <fcntl.h>
main()
{
int a;
a = open("love", O_WRONLY|O_CREAT);
dup2(a, 1); // 표준출력을 a에 복제함.
printf("사랑해~~\n"); // printf()에 의한 표준출력이 a로 됨
}
[w0rm9@work PIPE]$ gcc -o dup2 dup2.c
[w0rm9@work PIPE]$ ./dup2
[w0rm9@work PIPE]$ cat love
사랑해~~
0x03. 명명 파이프 : FIFO
popen()의 단점인 한 프로세스와 popen()의해 실행된 프로세스간의 통신에서 모든 프로세스가 명명 파이프를 통해 통신가능
사용법)
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename, mode_t mode);
int mknod(const char *filename, mode_t mode | S_IFIFO, (dev_t) 0);
=> 명명 파이프를 mode와 filename를 참조하여 생성한다.
테스트)
[w0rm9@work PIPE]$ cat fifo1.c
#include <stdio.h>
#include <fcntl.h>
int main()
{
int pipe_fd;
mkfifo("/tmp/fifo_tmp", 0777);
pipe_fd = open("/tmp/fifo_tmp", O_WRONLY); // 명명 파이프를 생성
write(pipe_fd, "사랑해", 7); // 명명 파이프를 통해 쓴다.
close(pipe_fd);
}
[w0rm9@work PIPE]$ gcc -o fifo1 fifo1.c
[w0rm9@work PIPE]$ cat fifo2.c
#include <stdio.h>
#include <fcntl.h>
int main()
{
int pipe_fd;
char string[16];
pipe_fd = open("/tmp/fifo_tmp", O_RDONLY); // 명명 파이프를 연다.
read(pipe_fd, string, 7); // 읽어들인다.
printf("%s\n", string);
close(pipe_fd);
}
[w0rm9@work PIPE]$ gcc -o fifo2 fifo2.c
[w0rm9@work PIPE]$ ./fifo1 &
[1] 15686
[w0rm9@work PIPE]$ ./fifo2
사랑해
[1]+ Done ./fifo1
_eof_
