340 likes | 558 Views
Chapter 7. Pipe. http://network.hanbat.ac.kr. pipe 개요. Simple IPC (inter process communication) mechanism 두 프로세스간 통신 기능 제공 동작 방식 수도관 (pipe) 을 통해서 흐르는 물 ( 데이터 ) 과 유사 Writing process 와 Reading process 사이에 동기화를 제공 Writing process 가 아직 write 를 하지 않은 파이프에서 read 하는 경우 read(2) 가 block
E N D
Chapter 7. Pipe http://network.hanbat.ac.kr
pipe 개요 • Simple IPC (inter process communication) mechanism • 두 프로세스간 통신 기능 제공 • 동작 방식 • 수도관(pipe)을 통해서 흐르는 물(데이터)과 유사 • Writing process와 Reading process 사이에 동기화를 제공 • Writing process가 아직 write를 하지 않은 파이프에서 read 하는 경우 • read(2)가 block • Reading process가 읽지 않고, writing process가 계속 write하여 파이프가 가득 찬 경우 • write(2)가 block
pipe(2) #include <unistd.h> int pipe (int filedes[2]); • pipe의 생성 • 수행결과 • filedes[0] • 파이프에서 읽기 위한 file descriptor 값이 저장됨 • filedes[1] • 파이프에 쓰기를 위한 file descriptor 값이 저장됨 • Return • Success : 0 • Failure : -1 and erron is set
pipe(2) 적용 가능한 시스템 호출들 • open(2) • 사용 안됨 • close(2) • 파이프로의 접근이 완료되었을 때 사용 • read(2) • 파이프가 비어있다면 멈춤(block) • write(2) • 파이프가 꽉 차있다면 멈춤(block) • lseek(2) • 사용 안됨 • dup(2) • 파이프로의 입출력 방향을 변경(redirection)을 위해 사용됨 • fcntl(2) • 입출력시 지연이 없도록 함
#include<stdio.h> #define MSGSIZE 20 main (int argc, char *argv[]) { int fd[2], pid; char msgin[MSGSIZE], msgout[MSGSIZE] = "\nHello, world\n"; if (pipe(fd) == -1) { perror(argv[0]); exit(1); } if ((pid = fork()) > 0) { /* parent */ write (fd[1], msgout, MSGSIZE); } else if (pid == 0) { /* child */ read (fd[0], msgin, MSGSIZE); puts (msgin); } }
% gcc q.c % a.out % Hello, world %
who.c #include <stdio.h> char text[80]; main (int argc, char **argv) { int fd[2]; if (pipe(fd) == -1) { perror(argv[0]); exit(1); } if (fork() == 0) { /* first child */ close (1); dup (fd[1]); /* redirect std output */ close (fd[0]); close (fd[1]); printf ("who display sorted\n"); fflush (stdout); execl ("/usr/bin/who", "who", (char*) 0); exit (127); }
who.c: 계속 if (fork() == 0) { /* second child */ close (0); dup (fd[0]); /* redirect std input */ close (fd[0]); close (fd[1]); read2line (text); printf ("\tHeading: %s\n", text); fflush (stdout); /* sort는 stdin입력, stdout출력 */ execl ("/bin/sort", "sort", (char*) 0); exit (127); } close (fd[0]); close (fd[1]); while (wait((char*)0) != -1) ; exit(0); } read2line(char *input) { while (1) { read (0, input, 1); if (*input == '\n') break; else input++; } }
% a.out Heading: who display sorted dksung pts/5 5월 17 09:03 (202.30.46.39) egkim pts/9 5월 18 17:27 (203.230.107.166) root console 4월 7 11:23 (:0) root pts/3 4월 7 11:23 (:0.0) root pts/8 5월 17 10:43 (:0.0) %
% a.out this is test... [Parent] : Send Message : this is test... [Child] : Receive Message : this is test... [Child] : Send Message : this is test... [Parent] : Receive Message : this is test... %
create_pipe1.c: 학생들이 직접 읽고 해석. #include <stdio.h> #include <unistd.h> #include <errno.h> #define MAX_SIZE 50 main() { int send_fd[2], rcv_fd[2], pid=0, size=0; char send_buf[MAX_SIZE], rcv_buf[MAX_SIZE]; memset (send_buf, 0x00, MAX_SIZE); memset (rcv_buf, 0x00, MAX_SIZE); if ( pipe(send_fd) == -1 ) { perror("pipe() : "); exit(1); } if ( pipe(rcv_fd) == -1 ) { perror("pipe() : "); exit(2); }
if ((pid = fork()) == 0 ) { /* Child */ close(send_fd[1]); close(rcv_fd[0]); size = read(send_fd[0], rcv_buf, MAX_SIZE); printf("\t[Child] : Receive Message : %s\n", rcv_buf); write(rcv_fd[1], rcv_buf, size); printf("\t[Child] : Send Message : %s\n", rcv_buf); exit(0); } else if ( pid > 0 ) { /* Parent */ close(send_fd[0]); close(rcv_fd[1]); size = read(0, send_buf, MAX_SIZE); write(send_fd[1], send_buf, size); printf("[Parent] : Send Message : %s\n", send_buf); read(rcv_fd[0], rcv_buf, MAX_SIZE); printf("[Parent] : Receive Message : %s\n", rcv_buf); } }
create_pipe2.c #include <stdio.h> #include <unistd.h> #include <errno.h> #define MAX_SIZE 50 main (int argc, char *argv[]) { int fd[2], pid=0, size=0, status=0; char buf[MAX_SIZE]; memset (buf, 0x00, MAX_SIZE); if ( pipe(fd) == -1 ) { perror("pipe() : "); exit(1); } if ( fork() == 0 ) { close(0); dup(fd[0]); close(fd[0]); close(fd[1]); size = read(0, buf, MAX_SIZE); execlp(buf, buf, (char *)NULL); perror("execlp() : "); exit(3); }
if ( fork() == 0 ) { close (1); dup (fd[1]); close (fd[0]); close (fd[1]); printf ("%s", argv[1]); fflush (stdout); exit(0); } close (fd[0]); close(fd[1]); while ( wait(&status) != -1 ) ; exit(0); }
% a.out date 2004. 05. 19. (수) 11:28:16 KST %
실습 • 7 page • 10 ~ 12 page • 16 ~ 17 page • 학생들이 직접 읽고 해석한 이후에 실습 • 유사한 시험 문제 나올 수 있음. • 19 ~ 20 page
Pipe 표준 라이브러리 • 생략
mknod(1) • Create a special file • Block special file • /dev/hda: hard-disk brw-rw---- 1 root disk 3, 0 Mar 24 2001 /dev/hda • Character special file • /dev/tty crw-rw-rw- 1 root root 5, 0 Mar 24 2001 /dev/tty • FIFO • Named pipe를 위한 파일 prw-rw-r-- 1 egkim egkim 0 Mar 19 19:17 pipeFile • Named pipe를 위한 special file의 생성 % mknod pipeFile p %
% cat data 1 abcdefghijklmnopqrstuvwxyz 2 abcdefghijklmnopqrstuvwxyz 3 abcdefghijklmnopqrstuvwxyz % % ls data % mknod NP p % ls NP data % cat NP blocking until data received 1 abcdefghijklmnopqrstuvwxyz 2 abcdefghijklmnopqrstuvwxyz 3 abcdefghijklmnopqrstuvwxyz % % % cat data > NP send data to NP % mknod(1)의 사용 예: Shell
mknod(3): #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int mknod (const char *pathname, mode_t mode, dev_t dev); • Create a directory or special or ordinary file • Parameter • pathname: 경로를 포함하는 파일 이름 • mode: 생성하려는 파일의 permission 및 type (“|”로 조합) • Type • S_IFREG (일반 파일), S_IFCHR (character special file), S_IFBLK (block special file), S_IFIFO (named pipe) • 예: mknod (“pipeFile ”, S_IFIFO | 0660, 0); • dev: FIFO용 으로는 사용하지 않음 • Return • Success : 0 • Failure : -1 and errno is set
Named pipe에 적용 가능한 시스템 호출들 • open(2) • 정규 파일에서와 동일하게 사용 • clos(2) • Named pipe로의 접근이 완료되었을 때 사용 • read(2) • 일반적으로 데이터가 없으면 멈춤(block) • write(2) • 일반적으로 파이프에 데이터가 꽉 차면 멈춤(block) • lseek(2) • 사용하지 않음 • dup(2) • 파이프로 입출력 방향을 변경(redirection)을 위해 사용됨 • fcntl(2) • 입출력을 위한 지연이 없도록 set 할 때 사용
Client – Server Program • namedPipe.h struct message { char privfifo[15]; /* name of private named pipe */ char filename[100]; /* name of file */ }; #define PUBLIC "Public" #define LINESIZE 512 #define NUMTRIES 3
file_server.c #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include "namedPipe.h" main (int argc, char *argv[]) { int fdpub, fdpriv, fd, n, i; struct message msg; char line[LINESIZE]; /* mknod(1)을 이용하여, FIFO special file을 만들지 않았으면 생성 */ /* 이미 만들어져 있으면, mknod(2) 에러 발생 무시 */ mknod (PUBLIC, S_IFIFO|0666, 0); if ((fdpub = open(PUBLIC, O_RDONLY)) == -1) { perror(PUBLIC); exit(1); }
loop: /* forever */ while (read(fdpub, (char *) &msg, sizeof(msg)) >0) { printf (“Client Request Arrived.\n”); if ((fd=open(msg.filename, O_RDONLY)) == -1) { perror(msg.filename); break; } for (i= 0; i< NUMTRIES; i++) if ((fdpriv = open(msg.privfifo, O_WRONLY|O_NDELAY)) == -1) sleep(1); else break; if (fdpriv == -1) { perror (msg.privfifo); break; } while ((n=read(fd, line, LINESIZE)) > 0) write (fdpriv, line, n); close (fd); close (fdpriv); } goto loop; }
client.c #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "namedPipe.h" main (int argc, char *argv[]) { struct message msg; int n, fdpub, fdpriv; char line[LINESIZE]; sprintf (msg.privfifo, "Fifo%d", getpid()); if (mknod(msg.privfifo, S_IFIFO| 0666, 0) == -1) { perror(msg.privfifo); exit(1); }
if ((fdpub = open(PUBLIC, O_WRONLY)) == -1) { perror (PUBLIC); exit(2); } strcpy (msg.filename, argv[1]); write (fdpub, (char *) &msg, sizeof(msg)); if ((fdpriv = open(msg.privfifo, O_RDONLY)) ==-1) { perror (msg.privfifo); exit(3); } while ((n=read(fdpriv, line, LINESIZE)) > 0) write(1,line,n); close (fdpriv); unlink (msg.privfifo); exit(0); }
% gcc -o server server.c % gcc -o client client.c % % server Client Request Arrived. % cat data 1 abcdefghijklmnopqrstuvwxyz 2 abcdefghijklmnopqrstuvwxyz 3 abcdefghijklmnopqrstuvwxyz % % client data 1 abcdefghijklmnopqrstuvwxyz 2 abcdefghijklmnopqrstuvwxyz 3 abcdefghijklmnopqrstuvwxyz %