1 / 34

Linux System Programming

Linux System Programming. Lecture #8 – 파이프 (Pipe). 파이프 (Pipe) (1). 파이프 (Pipe) 정의 : 하나의 프로세스를 다른 프로세스에 연결시켜 주는 일방 통행의 통신 채널 리눅스의 파일 개념을 일반화한 프로세스 통신 객체 파일 입출력 시스템 호출을 통해 접근이 가능 하나의 프로세스가 write 시스템 호출을 이용하여 데이터를 파이프를 통해 전송하면 , 다른 프로세스가 read 시스템 호출을 이용하여 데이터를 읽어 들일 수 있다

kalb
Download Presentation

Linux System Programming

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. Linux System Programming Lecture #8 –파이프(Pipe)

  2. 파이프(Pipe) (1) • 파이프(Pipe) 정의: • 하나의 프로세스를 다른 프로세스에 연결시켜 주는 일방 통행의 통신 채널 • 리눅스의 파일 개념을 일반화한 프로세스 통신 객체 • 파일 입출력 시스템 호출을 통해 접근이 가능 • 하나의 프로세스가 write 시스템 호출을 이용하여 데이터를 파이프를 통해 전송하면, 다른 프로세스가 read 시스템 호출을 이용하여 데이터를 읽어 들일 수 있다 • 프로세스들 사이에 데이터를 FIFO 방식으로 전달할 수 있게 하며, 프로세스 수행의 동기화를 지원 • 일잔적으로 파일 시스템을 이용하여 파이프를 구현 Linux System Programming

  3. 파이프(Pipe) (2) • 파이프(Pipe) 정의: • 정규 파일과 파이프의 비교: Linux System Programming

  4. 파이프(Pipe) (3) • 파이프(Pipe) 종류: • 파이프의 종류 • 명명된 파이프(Named Pipe) • 비명명된 파이프(Unnamed Pipe) –보통 ‘파이프’라고 함 • 명명된 파이프와 비명명된 파이프의 비교 Linux System Programming

  5. 프로세스 A 프로세스 B 프로세스 C 프로세스 D 프로세스 E 파이프 접근 가능 파이프(Pipe) (3) • 파이프(Pipe) 접근 권한: • 명명된 파이프의 접근 권한 • 접근 허가 모드 설정을 통해 제한 • 비명명된 파이프의 접근 권한 파이프 생성 Linux System Programming

  6. Pipe 시스템 호출 (1) • Pipe 시스템 호출: • 비명명된 파이프를 생성 Linux System Programming

  7. Pipe 시스템 호출 (2) • 비명명된 파이프 접근 시스템 호출: Linux System Programming

  8. Pipe 시스템 호출 (3) • 리눅스 시스템에서의 파이프 구현 • 파일시스템에서 임시 파일을 생성하여 파이프를 지원 Linux System Programming

  9. Pipe 시스템 호출 (4) • 예제 8-1 • 비명명된 파이프를 생성하여 부모 프로세스에서 메시지를 보내고 자식 프로세스에서 메시지를 출력하는 프로그램 #define MSGSIZE 20 main(argc,argv) int argc; char *argv[]; { int fd[2], pid, pipe(), fork(); static char msgout[MSGSIZE] = "Hello, world\n"; static char msgin[MSGSIZE]; if(pipe(fd) == -1) { perror(argv[0]); exit(1); } Linux System Programming

  10. Pipe 시스템 호출 (5) if((pid = fork()) > 0) { /* parent */ write(fd[1], msgout, MSGSIZE); } else if(pid == 0) { /* child */ read(fd[0], msgin, MSGSIZE); puts(msgin); } else { /* cannot fork */ perror(argv[0]); exit(2); } exit(0); } Linux System Programming

  11. Pipe 시스템 호출 (6) • 예제 8-2 • 두 개의 자식 프로세스를 파이프를 생성하여 통신하는 프로그램 #include <stdio.h> char text[80]; main(int argc, char *argv[]) { int fd[2], pipe(), fork(), wait(); if(pipe(fd) == -1) { perror(argv[0]); exit(1); } if(fork() == 0) { /* first child */ close(1); dup(fd[1]); /* redirection std output */ close(fd[0]); close(fd[1]); printf("who display sorted\n"); fflush(stdout); execl("/usr/bin/who","who",(char *) 0); exit(127); } Linux System Programming

  12. Pipe 시스템 호출 (7) if(fork() == 0) { /* second child */ close(0); dup(fd[0]); /* redirection std output */ close(fd[0]); close(fd[1]); read_to_nl(text); printf("Heading: %s\n",text); fflush(stdout); execl("/bin/sort","sort",(char *) 0); exit(127); } close(fd[0]); close(fd[1]); while(wait((int *) 0) != -1) ; /* null */ exit(0); } read_to_nl(input) char *input; { while(1) { read(0, input, 1); if(*input == '\n') break; else input++; } } Linux System Programming

  13. 파이프 라이브러리 함수 (1) • 파이프 라이브러리 함수: popen(), pclose() • 비명명된 파이프를 생성하고 닫는 라이브러리 함수 • 정규파일을 열고 닫는 fopen()/fclose()와 유사 Linux System Programming

  14. 파이프 라이브러리 함수 (2) • 파이프 라이브러리 함수의 실행 과정 • popen() 함수 – fork()/exec()/pipe()/dup()을 이용하여 구현 • pclose() 함수 – wait()/close()를 이용하여 구현 Linux System Programming

  15. 파이프 라이브러리 함수 (3) • 예제 8-3 • 파이프 표준 라이브러리 함수 popen()/pclose()를 사용하여 리눅스 명령어 “who | sort”를 실행하는 프로그램 #include <stdio.h> main() { FILE *fpin, *fpout; char line[BUFSIZ]; fpin = popen("who","r"); fpout = popen("sort","w"); while(fgets(line, BUFSIZ, fpin) != (char *) NULL) fputs(line,fpout); pclose(fpin); pclose(fpout); } Linux System Programming

  16. 명명된 파이프(Named Pipe) (1) • 명명된 파이프(Named Pipe) • 비명명된 파이프의 문제점 • 첫째, 파이프는 부무와 자식 프로세스와 같이 연관된 프로세스만이 접근 가능하다 • 둘째, 파이프는 영구히 존재할 수 없다 –파이프는 필요할 때에 만들어지고 파이프와 관계된 프로세스가 종료할 때에 소멸한다 • 시스템 전체에 대해 서비스를 제공하는 서버(server)를 개발하고자 할 때에 문제가 발생 • 명명된 파이프 또는 FIFO • 비명명된 파이프와 같이 프로세스간의 통신 및 동기화 기능 지원 • 파일 시스템에서 특수 파일 형태로 영구 존재 • 리눅스 파일 이름을 부여하고 접근 허가 설정을 통해 모든 프로세스가 접근 가능 • 비명명된 파이프와 동일한 방법으로 시스템 호출을 사용하여 접근 Linux System Programming

  17. 명명된 파이프(Named Pipe) (2) • 명명된 파이프(Named Pipe) 생성 : • mknod 시스템 호출 Linux System Programming

  18. 명명된 파이프(Named Pipe) (3) • 명명된 파이프(Named Pipe) 생성 : • mknod 시스템 호출의 매개 변수 생성되는 파일 유형 : 파일 생성 허가 모드 : Linux System Programming

  19. 명명된 파이프(Named Pipe) (4) • 예제 8-4 • 다음 그림과 같은 기능을 지원하는 파일 서버/클라이언트(server/client) 프로그램 Linux System Programming

  20. 명명된 파이프(Named Pipe) (5) // file name: ex8-4.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 Linux System Programming

  21. 명명된 파이프(Named Pipe) (6) // file name: ex8-4a.c // #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "ex8-4.h" main(argc,argv) int argc; char *argv[]; { struct message msg; int n, getpid(); int fdpub, fdpriv, open(); char line[LINESIZE]; sprintf(msg.privfifo,"Fifo%d",getpid()); if(mknod(msg.privfifo, S_IFIFO| 0666, 0) == -1) { perror(msg.privfifo); exit(1); } Linux System Programming

  22. 명명된 파이프(Named Pipe) (7) 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); } Linux System Programming

  23. 명명된 파이프(Named Pipe) (8) // file name: ex8-4b.c // #include <fcntl.h> #include "ex8-4.h" main(argc,argv) int argc; char argv; { int fdpub, fdpriv, fd, open(); struct message msg; int n; char line[LINESIZE]; loop: /* forver */ if((fdpub = open(PUBLIC, O_RDONLY)) == -1) { perror(PUBLIC); exit(1); } Linux System Programming

  24. 명명된 파이프(Named Pipe) (9) while(read(fdpub, (char *) &msg,sizeof(msg)) >0) { if((fd=open(msg.filename,O_RDONLY)) == -1) { perror(msg.filename); break; } if((fdpriv=open(msg.privfifo,O_WRONLY)) == -1) { perror(msg.privfifo); break; } while((n=read(fd,line,LINESIZE)) > 0) write(fdpriv, line, n); close(fd); close(fdpriv); } close(fdpub); goto loop; } Linux System Programming

  25. 예제 프로그램 (1) • 예제 8-6: • 파이프를 통하여 통신하는 두 개의 프로세스를 생성하고, 부모 프로세스는 소문자로 된 문장을 파이프를 통해 전송하고, 자식 프로세스는 파이프에서 데이터를 읽어 대문자로 변환하여 출력하는 프로그램 #include <ctype.h> main(int argc, char *argv[]) { int pid, fd[2]; static char *line[3] = { "Here are 3 lines of test.\n", "You will see all lower case\n", "made to upper!!\n" }; char input[1000]; int i, rtn; if(pipe(fd) == -1) { perror(argv[0]); exit(1); } Linux System Programming

  26. 예제 프로그램 (2) if((pid = fork()) > 0) { /* parent */ close(fd[0]); for(i=0; i<3 ; i++) write(fd[1],line[i],strlen(line[i])); close(fd[1]); } else if(pid == 0) { /* child */ close(fd[1]); while((rtn = read(fd[0], input, 1000)) > 0) { for(i=0; i<rtn; i++) if(islower(input[i])) input[i] = toupper(input[i]); write(1,input, rtn); } close(fd[0]); } else { /* cannot fork */ perror(argv[0]); exit(2); } exit(0); } Linux System Programming

  27. 예제 프로그램 (3) • 예제 8-8: • 리눅스의 wc 명령어를 이용하여 파일에 포함되어 있는 공백 라인을 계수하여 출력하는 프로그램 • 파이프 표준 라이브러리 함수(popen, pclose)를 이용하여 작성 #include <stdio.h> #define TRUE 1 #define FALSE 0 main(int argc, char *argv[]) { FILE *fpin, *fpout; char line[BUFSIZ]; int strlen(); if((fpin = fopen(argv[1], "r")) == (FILE *) NULL) { perror(argv[0]); exit(1); } Linux System Programming

  28. 예제 프로그램 (4) fpout = popen("wc -l","w"); while (fgets(line, BUFSIZ, fpin) != (char *) NULL) if(line[0] == '\n') fputs(line,fpout); fclose(fpin); pclose(fpout); } Linux System Programming

  29. 예제 프로그램 (5) • 예제 8-9: • 미니 셀(mini-shell) 프로그램 ex7-16.c를 파이프 라인 기능이 가능하도록 수정하여라 • 교재의 프로그램 ‘ex8-9.c’를 참조 Linux System Programming

  30. 예제 프로그램 (6) • 예제 8-10: • 숫자 맞추기 게임 프로그램: • 두 개의 프로그램은 명명된 파이프를 통해 통신한다 • 첫번째 프로그램은 명명된 파이프(FIFO)를 생성하고 임의의 숫자를 난수로 발생한다 • 첫번째 프로그램은 두번째 프로그램은에서 FIFO를 통하여 전송한 숫자가 정답과 비교하여 크면 ‘H’, 작으면 ‘L’, 같으면 ‘E’이라는 메시지를 FIFO를 통해 두번째 프로그램에 전송한다 • 두번째 프로그램은 경기자가 추측하여 응답한 숫자를 FIFO를 통하여 첫번째 프로그램으로 전송하고, 그값이 크다(H), 작다(L), 같다(E)와 같은 응답을 받아 화면에 출력하여 숫자를 맞출 때까지 반복한다 • 두 개의 파이프를 생성하여 질문과 응답을 전달하는 통신 채널로 사용한다 Linux System Programming

  31. 예제 프로그램 (7) // file name: ex8-10a.c // #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define GUESSFIFO "Guessfifo" #define RESPNSFIFO "Respnsfifo" main(argc,argv) int argc; char *argv[]; { int number, guess, rand(); int fdguess, fdresp, open(); if(mknod(GUESSFIFO, S_IFIFO | 0666, 0) == -1) { perror(GUESSFIFO); exit(1); } if(mknod(RESPNSFIFO, S_IFIFO | 0666, 0) == -1) { perror(RESPNSFIFO); exit(2); } Linux System Programming

  32. 예제 프로그램 (8) if((fdguess = open(GUESSFIFO, O_RDONLY)) == -1) { perror(GUESSFIFO); exit(3); } if((fdresp = open(RESPNSFIFO, O_WRONLY)) == -1) { perror(RESPNSFIFO); exit(4); } number = rand() % 1000; while(read(fdguess, (char *) &guess, sizeof(guess)) > 0) { if(guess > number) write(fdresp, "H", 1); else if(guess < number) write(fdresp, "L", 1); else write(fdresp, "E", 1); } close(fdguess); close(fdresp); unlink(GUESSFIFO); unlink(RESPNSFIFO); exit(0); } Linux System Programming

  33. 예제 프로그램 (9) // file name: ex8-10b.c // #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define GUESSFIFO "Guessfifo" #define RESPNSFIFO "Respnsfifo" main(int argc, char *argv[]) { int higuess, loguess, guess; int fdguess, fdresp, open(); char response; if((fdguess = open(GUESSFIFO, O_WRONLY)) == -1) { perror(GUESSFIFO); exit(1); } if((fdresp = open(RESPNSFIFO, O_RDONLY)) == -1) { perror(RESPNSFIFO); exit(2); } Linux System Programming

  34. 예제 프로그램 (10) loguess = 0; higuess = 1000; guess = 500; write(fdguess, (char *) &guess, sizeof(guess)); while(read(fdresp, &response, 1) > 0) { if(response == 'H') { printf("%d is too high\n",guess); higuess = guess; guess = (higuess + loguess) / 2; } else if(response == 'L') { printf("%d is too low\n",guess); loguess = guess; guess = (higuess + loguess) / 2; } else { printf("%d is correct\n",guess); break; } write(fdguess, (char *) &guess, sizeof(guess)); } close(fdguess); close(fdresp); exit(0); } Linux System Programming

More Related