1 / 36

[Unix Programming] Interprocess Communication - PIPE

[Unix Programming] Interprocess Communication - PIPE. Young-Ju, Han Email: yjhan@imtl.skku.ac.kr. Contents. Pipes Using pipe a single process Using pipe a multiple processes Using pipe in the shell. Overview. different forms of IPC pipes(half duplex) FIFOs(named pipes)

dobry
Download Presentation

[Unix Programming] Interprocess Communication - PIPE

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. [Unix Programming]Interprocess Communication - PIPE Young-Ju, Han Email: yjhan@imtl.skku.ac.kr

  2. Contents • Pipes • Using pipe a single process • Using pipe a multiple processes • Using pipe in the shell 2007 UNIX Programming

  3. Overview • different forms of IPC • pipes(half duplex) • FIFOs(named pipes) • stream pipes(full duplex) • named stream pipes • message queues • semaphores • shared memory • sockets • streams on the same host on different host 2007 UNIX Programming

  4. Pipes • only form of IPC on all UNIX implementations • The oldest form of UNIX IPC • most commonly used form of IPC • limitations • half-duplex • one-way communication channel • used only between processes that have a common ancestor (related processes) stream pipes FIFOs & named stream pipes 2007 UNIX Programming

  5. Pipes • Pipes • connects the standard output of one programto the standard input of another program I/O Redirections and Pipelines stdin file1 stderr myprog1 stdout stdin stderr myprog2 Stdout file2 $ (myprog1 | myprog2 ) < file1 > file2 2007 UNIX Programming

  6. Pipes • Pipes at command level (Example) I/O Redirection and Pipelines Method 1. I/O Redirection Method $ ls /home/kc > tempfile $ wc -l < tempfile 19 $ rm tempfile 2. Pipeline Method $ ls /home/kc | wc -l 19 2007 UNIX Programming

  7. Pipes • pipes at command level Weak Point of I/O Redirection Method 1. Cannot create temporary files if you don’t have permission 2. May have a invalid result because of temporary file 3. Easy to forget to remove temporary file (Example) cd /bin 1. I/O Redirection Method (Failure) $ ls > tempfile tempfile: permission denied 2. Pipeline Method ( Success) $ ls | wc -l 777 2007 UNIX Programming

  8. pipes • %who | sort 2007 UNIX Programming

  9. Create pipes pipe() system call Data transmitting data is written into pipes using the write() system call data is read from a pipe using the read() system call automatic blocking when full or empty FIFO basis, so lseek() don’t work Types of pipes (unnamed) pipes named pipes Pipes 2007 UNIX Programming

  10. Pipes • Programming with pipes • create a pipe #include <unistd.h> int pipe (int fd[2]); fd[0] : read only open fd[1] : write only open 0 : ok -1 : error more open than per-user process limit(EMFILE) kernel’s open file table overflow(ENFILE) 2007 UNIX Programming

  11. Pipes • ex) pipe on a single process $a.out hello, world #1 hello, world #2 hello, world #3 #include <stdio.h> #include <unistd.h> #define MSGSIZE 1024 char *msg1= “hello, world #1”; char *msg2= “hello, world #2”; char *msg3= “hello, world #3”; int main(){ char inbuf[MSGSIZE]; int fd[2], j, ret; if (pipe(fd) == -1) {perror(“pipe call”); exit(1);} write(fd[1], msg1, strlen(msg1)); write(fd[1], msg2, strlen(msg2)); write(fd[1], msg3, strlen(msg3)); for (j = 0; j < 3; j++) { ret = read(fd[0], inbuf, MSGSIZE); inbuf[ret]=0; printf(“%s\n”, inbuf); } } 2007 UNIX Programming

  12. Pipes • ex) pipe on a single process process process or fd[0] fd[1] fd[0] fd[1] pipe kernel • read in the order in which they were written • first in/first out(FIFO) communication channel • => Since lseek don’t work on a pipe 2007 UNIX Programming

  13. Pipes • kernel’s pipe buffer size • constant PIPE_BUF • rule • if a write overfill pipe, then blocked until reading • if a read when empty, then blocked until writing • if a write > pipe, then block after write • if a read > pipe, then return after read pipe_size = fpathconf( p[0], _PC_PIPE_BUF ); 2007 UNIX Programming

  14. Pipes • rules (when one end of a pipe is closed) • If we read from a pipe whose write end has been closed, • after all the data has been read, read return 0 to indicate an end of file • End of file is not generated until there are no more writers for the pipe • If we write to a pipe whose read end has been closed, • the signal SIGPIPE is generated • Default action : terminate 2007 UNIX Programming

  15. Pipes • ex) pipe from child to parent $a.out hello, world #1 hello, world #2 hello, world #3 => 무한 대기 int main(){ char inbuf[MSGSIZE]; int fd[2], j; pid_t pid; if (pipe(fd) == -1) {perror(“pipe call”); exit(1);} switch(pid = fork()) { case -1 : perror(“fork error”); exit(1); case 0 : write(fd[1], msg1, strlen(msg1)); write(fd[1], msg2, strlen(msg1)); write(fd[1], msg3, strlen(msg1)); break; default : for (j = 0; j < 3; j++) { read(fd[0], inbuf, MSGSIZE); inbuf[ret] = 0; printf(“%s\n”, inbuf); } wait(NULL); } } 무한대기 2007 UNIX Programming

  16. Pipes • ex) pipe from child to parent parent child fork fd[0] fd[1] fd[0] fd[1] write() read() pipe kernel 2007 UNIX Programming

  17. Pipes • ex) pipe from child to parent (recommended) switch(pid = fork()) { case -1 : perror(“fork error”); exit(1); case 0 : close(fd[0]); write(fd[1], msg1, MSGSIZE); write(fd[1], msg2, MSGSIZE); write(fd[1], msg3, MSGSIZE); break; default : close(fd[1]); for (j = 0; j < 3; j++) { read(fd[0], inbuf, MSGSIZE); printf(“%s\n”, inbuf); } wait(NULL); } 2007 UNIX Programming

  18. Pipes • pipe from child to parent (recommended) parent child fork fd[0] fd[1] write() read() pipe kernel 2007 UNIX Programming

  19. Pipes • Non-blocking reads and writes • to use fstat • If st_size > 0 , and then read() from pipe • st_size : number of characters currently in the pipe • problem : if several processes are reading the pipe, another process could read from a pipe in the gap between fstat and read • to use fcntl ( recommend) • O_NONBLOCK flag • errno -1 : EAGAIN #include <fcntl.h> if( fcntl(fd, F_SETFL, O_NONBLOCK) == -1 ) perror(“fcntl”); 2007 UNIX Programming

  20. Pipes • Non-blocking read and write #include <fcntl.h> #include <errno.h> #define MSGSIZE 6 int parent (int *); int child (int *); char *msg1 = "hello"; char *msg2 = "bye!!"; void fatal(char* msg) { fprintf(stderr,”%s\n”,msg);exit(1);} int main(){ int pfd[2]; /* 파이프를 개방한다 */ if(pipe (pfd) == -1) fatal ("pipe call"); /* p[0]의 O_NONBLOCK 플래그를 1로 설정한다 */ if (fcntl (pfd[0], F_SETFL, O_NONBLOCK) == -1) fatal ("fcntl call"); switch(fork()){ case -1: fatal("fork call"); /* 오류 */ case 0: child(pfd); /* 자식 */ default: parent (pfd); /* 부모 */ } } 2007 UNIX Programming

  21. Pipes • Non-blocking read and write int parent (int p[2]) { /* 부모의 코드 */ int nread; char buf[MSGSIZE]; close (p[1]); for(;;) { switch (nread = read(p[0], buf, MSGSIZE)){ case -1: /* 파이프에 아무것도 없는지 검사한다. */ if (errno == EAGAIN){ printf ("(pipe empty)\n"); sleep (1); break; } else { perror("read call"); exit(1);} case 0: /* 파이프가 닫혔음. */ printf ("End of conversation\n"); exit (0); default: printf ("MSG=%s\n", buf); } } } 2007 UNIX Programming

  22. Pipes $a.out (pipe empty) MSG=hello (pipe empty) (pipe empty) (pipe empty) MSG=hello (pipe empty) (pipe empty) (pipe empty) MSG=hello (pipe empty) (pipe empty) MSG=bye!! (pipe empty) End of conversation • Non-blocking read and write int child(int p[2])  {   int count;   close (p[0]);   for (count= 0; count < 3; count++)   {         write (p[1], msg1, MSGSIZE);         sleep(3);   }   /* 마지막 메시지를 보낸다 */   write (p[1], msg2, MSGSIZE);   exit (0); } 2007 UNIX Programming

  23. Pipes • Using select to handle multiple pipes • Server & client Applications parent fd1[0] fd2[0] fd3[0] read() pipe pipe pipe fork fork fork write() fd1[1] fd3[1] fd2[1] Child 3 Child 1 Child 2 2007 UNIX Programming

  24. Pipes • Using select to handle multiple pipes • nfds : specifies the range of file descriptors to be tested. • 0 ~ nfds-1 • readfds : the specified file descriptors is ready for reading • writefds : FDs is ready for writing • errorfds : FDs is ready for error checking • Timeout • Timeout = NULL : block forever or until something of interest turns up • timeout.tv_sec = 0 && timeout.tv_usec = 0: returns immediately without blocking • Timeout.tv_sec != 0 || timeout.tv_usec != 0 : return after that number of tv_sec or tv_usec specified if there is no FDs activity #include <sys/time.h> int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set* errorfds, struct timeval *timeout); #include <sys/time.h> struct timeval { long tv_sec; /*second */ long tv_usec; /*microseconds */ } 0 : timeout, -1 : error >0 : the number of “interesting” FDs 2007 UNIX Programming

  25. Pipes • Macro for manipulating sets of file descriptor (bit mask) #include <sys/time.h> /* initialize the mask pointed to by fdset */ void FD_ZERO(fd_set *fdset); /* set the bit, fd, in the mask pointed to by fdset */ void FD_SET(int fd, fd_set* fdset); /* is the bit, fd, set in the mask pointed to by fdset */ void FD_ISSET(int fd, fd_set* fdset); /* turn off the bit, fd, in the mask pointed to by fdset */ void FD_CLR(int fd, fd_set *fdset); 2007 UNIX Programming

  26. Pipes • Using select to handle multiple regular files #include <sys/time.h> #include <sys/types.h> #include <fcntl.h> . . . int fd1, fd2; fd_set readset; fd1 = open(“file1”, O_RDONLY); fd2 = open(“file2”, O_RDONLY); FD_ZERO(&readset); FD_SET(fd1, &readset); FD_SET(fd2, &readset); switch(select(5,&readset,NULL,NULL,NULL)) { /* logic */ } select(fd2+1,&readset,NULL,NULL,NULL) Not recommended 2007 UNIX Programming

  27. pipes • Examples (Using select to handle multiple pipes) #include <sys/time.h> #include <sys/wait.h> #include <stdio.h> #include <unistd.h> #define MSGSIZE 6 char *msg1 = "hello"; char *msg2 = "bye!!"; void parent(int a[][]); int child(int b[]); void fatal(char* msg){ fprintf(stderr,"%s\n",msg);exit(1);} int main(){ int pip[3][2]; int i; for (i = 0; i < 3; i++) { if (pipe(pip[i]) == -1) fatal("pipe call"); switch (fork()){ case -1: /* 오류 */ fatal("fork call"); case 0: /* 자식 */ child(pip[i]); } } parent(pip); /* 부모 */ exit(0); } 2007 UNIX Programming

  28. pipes • Examples (parent process) void parent(int p[3][2]){ char buf[MSGSIZE], ch; fd_set set, master; int i; for (i = 0; i < 3; i++) close(p[i][1]); FD_ZERO(&master); FD_SET(0, &master); for (i = 0; i <3; i++) FD_SET(p[i][0], &master); while(set=master, select (p[2][0]+1, &set, NULL, NULL, NULL) > 0){ if(FD_ISSET(0, &set)){ /* standard input check */ printf ("From standard input..."); read (0, &ch, 1); printf("%c\n", ch); } for (i = 0; i < 3; i++) { if(FD_ISSET(p[i][0], &set)) { if(read(p[i][0], buf, MSGSIZE) > 0) { printf ("Message from child%d\n", i); printf ("MSG=%s\n",buf); } } } if(waitpid (-1, NULL,WNOHANG) == -1) return; } } 2007 UNIX Programming

  29. pipes • Examples (child process) $a.out Message from child0 MSG=hello Message from child1 MSG=hello Message from child2 MSG=hello Message from child2 MSG=hello Message from child2 MSG=bye!! d From standard input...d From standard input... Message from child0 MSG=hello . . . int child(int p[2]){ int count; close(p[0]); for (count = 0; count < 2; count++) { write (p[1], msg1, MSGSIZE); sleep (getpid()%4); } write (p[1], msg2, MSGSIZE); exit (0); } 2007 UNIX Programming

  30. Shell /bin/sh parent pipe fd[1] fd[0] child ls child wc Sell pipe implementation • Pipes and the exec system call %ls –l | wc /* stdin에서 command read */ /* command parsing */ /* 2개의 command이고 둘이 pipe로 연결되어 있다면*/ int fd[2], c1; pipe(fd); c1 = fork (); If(!c1) { /*first child*/ close( fd[0] ); close(1); dup2( fd[1],1 ); close( fd[1]); execlp(/*ls –l first command */); } c2= fork (); If(!c2) { /*second child*/ close( fd[1] ); close(0); dup2( fd[0],0 ); close( fd[0]); execlp(/*wc second command */); } close( fd[0] ); close( fd[1] ); 2007 UNIX Programming

  31. Sell pipe implementation • dup(), dup2() • 사용중인파일 디스크립터의 복사본을 만듦 • dup()는 새 파일 디스크립터가 할당 • dup2()는 fd2를 사용 • 리턴 값 • 성공하면 복사된 새 파일 디스크립터, 실패하면 -1 • dup()는 할당 가능한 가장 작은 번호를 리턴 • dup2()는 fd2를 리턴 • dup2()는 복사본을 만들기 전에 기존의 fd2를 close함 #include <unistd.h> int dup(int fd); int dup2( int fd, int fd2); 2007 UNIX Programming

  32. Sell pipe implementation • Another method: The Join program parent wait() write() (stdout) read() (stdin) pipe P[1] P[0] Child 1 (com2) Child 2 (com1) 2007 UNIX Programming

  33. Sell pipe implementation • Pseudo-code form of the Join program Process forks, parent waits for child And child continues Child create a pipe Child then forks In child created by second fork (child 2): standard output is coupled to write end of pipe using dup2 excess file descriptors are closed program described by ‘com1’ is exec’ed In child of first fork (child 1): standard input is coupled to read end of pipe using dup2 excess file descriptors are closed program described by ‘com2’ is exec’ed 2007 UNIX Programming

  34. Sell pipe implementation • The Join program int join(char* com1[], char* com2[]){ int p[2], status; /* 명령을 수행할 자식을 생성한다. */ switch (fork()){ case -1: /* 오류 */ fatal ("1st fork call in join"); case 0: /* 자식 */ break; default: /* 부모 */ wait(&status); return (status); } /* 루틴의 나머지 부분으로 자식에 의해 수행된다. */ /* 파이프를 만든다. */ if (pipe(p) == -1) fatal ("pipe call in join"); 2007 UNIX Programming

  35. Sell pipe implementation • The Join program switch (fork()){/* 다른 프로세스를 생성한다. */ case -1: /* 오류 */ fatal ("2nd fork call in join"); case 0: /* 쓰는 프로세스 */ dup2 (p[1],1); /* 표준 출력이 파이프로 가게 한다. */ close (p[0]); /* 화일 기술자를 절약한다. */ close (p[1]); execvp (com1[0], com1); /* execvp가 복귀하면, 오류가 발생한 것임. */ fatal("1st execvp call in join"); default: /* 읽는 프로세스 */ dup2(p[0], 0); /* 표준 입력이 파이프로부터 오게 한다 */ close (p[0]); close (p[1]); execvp (com2[0], com2); fatal ("2nd execvp call in join"); }} 2007 UNIX Programming

  36. Sell pipe implementation • The Join program 앞서 join routine은 다음 프로그램을 이용하여 호출될 수 있다: #include <stdio.h> main() { char *one[4] = {"ls", "-l", "/usr/lib", NULL}; char *two[3] = {"grep", "∧d", NULL}; int ret; ret = join (one, two); printf ("join returned %d\n", ret); exit (0); } 2007 UNIX Programming

More Related