Top Banner
Linux System Linux System Programming Programming Lecture #8 – 파파파 (Pipe)
34

Linux System Programming

Jan 17, 2016

Download

Documents

kalb

Linux System Programming. Lecture #8 – 파이프 (Pipe). 파이프 (Pipe) (1). 파이프 (Pipe) 정의 : 하나의 프로세스를 다른 프로세스에 연결시켜 주는 일방 통행의 통신 채널 리눅스의 파일 개념을 일반화한 프로세스 통신 객체 파일 입출력 시스템 호출을 통해 접근이 가능 하나의 프로세스가 write 시스템 호출을 이용하여 데이터를 파이프를 통해 전송하면 , 다른 프로세스가 read 시스템 호출을 이용하여 데이터를 읽어 들일 수 있다 - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Linux System Programming

Linux System Linux System ProgrammingProgramming

Lecture #8 – 파이프 (Pipe)

Page 2: Linux System Programming

Linux System Programming 2

파이프 (Pipe) (1)파이프 (Pipe) (1)

파이프 (Pipe) 정의 : 하나의 프로세스를 다른 프로세스에 연결시켜 주는 일방 통행의

통신 채널 리눅스의 파일 개념을 일반화한 프로세스 통신 객체

파일 입출력 시스템 호출을 통해 접근이 가능하나의 프로세스가 write 시스템 호출을 이용하여 데이터를 파이프를 통해 전송하면 , 다른 프로세스가 read 시스템 호출을 이용하여 데이터를 읽어 들일 수 있다

프로세스들 사이에 데이터를 FIFO 방식으로 전달할 수 있게 하며 , 프로세스 수행의 동기화를 지원

일잔적으로 파일 시스템을 이용하여 파이프를 구현

Page 3: Linux System Programming

Linux System Programming 3

파이프 (Pipe) (2)파이프 (Pipe) (2)

파이프 (Pipe) 정의 : 정규 파일과 파이프의 비교 :

정규 파일 파이프

접근 권한 접근허가비트를 이용하여 무관한 프로세스들이 접근 가능

연관된 프로세스만이 접근 가능( 부모 - 자식 프로세스 )

수명프로세스의 수명과 무관파일 내의 데이터는 non-volatile

프로세스 수명과 동일파일 내의 데이터는 volatile

용량 고정된 용량을 초과할 수 없음연속적인 바잍 스트림이므로 무제한의 정보 전달이 가능일시적인 입출력 데이터 양은 적다

동기화 별도의 입출력 동기화가 필요 입출력 동기화를 지원

Page 4: Linux System Programming

Linux System Programming 4

파이프 (Pipe) (3)파이프 (Pipe) (3)

파이프 (Pipe) 종류 : 파이프의 종류

명명된 파이프 (Named Pipe) 비명명된 파이프 (Unnamed Pipe) – 보통 ‘파이프’라고 함

명명된 파이프와 비명명된 파이프의 비교

명명된 파이프 비명명된 파이프

이름 (ID) 접근을 위한 별도의 이름 가짐 이름을 가지지 않음

생성 및 접근 방법

open() 시스템 호출을 통해 생성접근을 위한 시스템 호출은 동일

pipe() 시스템 호출을 통해 생성접근을 위한 시스템 호출은 동일

접근 권한 이름을 통해 모든 프로세스가 접근 가능

연관된 프로세스 , 즉 부모와 자식 관계를 갖는 프로세스만 접근

수명영구적으로 존재 가능정규 파일과 같은 방법으로 조작

close() 시스템 호출에 의해 소멸

Page 5: Linux System Programming

Linux System Programming 5

파이프 (Pipe) (3)파이프 (Pipe) (3)

파이프 (Pipe) 접근 권한 : 명명된 파이프의 접근 권한

접근 허가 모드 설정을 통해 제한 비명명된 파이프의 접근 권한

프로세스 A

프로세스 B 프로세스 C

프로세스 D 프로세스 E

파이프 생성

파이프 접근 가능

Page 6: Linux System Programming

Linux System Programming 6

Pipe 시스템 호출 (1)Pipe 시스템 호출 (1)

Pipe 시스템 호출 : 비명명된 파이프를 생성

Page 7: Linux System Programming

Linux System Programming 7

Pipe 시스템 호출 (2)Pipe 시스템 호출 (2)

비명명된 파이프 접근 시스템 호출 :

Page 8: Linux System Programming

Linux System Programming 8

Pipe 시스템 호출 (3)Pipe 시스템 호출 (3)

리눅스 시스템에서의 파이프 구현 파일시스템에서 임시 파일을 생성하여 파이프를 지원

Page 9: Linux System Programming

Linux System Programming 9

Pipe 시스템 호출 (4)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);

}

Page 10: Linux System Programming

Linux System Programming 10

Pipe 시스템 호출 (5)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);

}

Page 11: Linux System Programming

Linux System Programming 11

Pipe 시스템 호출 (6)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);

}

Page 12: Linux System Programming

Linux System Programming 12

Pipe 시스템 호출 (7)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++;

}}

Page 13: Linux System Programming

Linux System Programming 13

파이프 라이브러리 함수 (1)파이프 라이브러리 함수 (1) 파이프 라이브러리 함수 : popen(), pclose()

비명명된 파이프를 생성하고 닫는 라이브러리 함수 정규파일을 열고 닫는 fopen()/fclose() 와 유사

Page 14: Linux System Programming

Linux System Programming 14

파이프 라이브러리 함수 (2)파이프 라이브러리 함수 (2) 파이프 라이브러리 함수의 실행 과정

popen() 함수 – fork()/exec()/pipe()/dup() 을 이용하여 구현 pclose() 함수 – wait()/close() 를 이용하여 구현

Page 15: Linux System Programming

Linux System Programming 15

파이프 라이브러리 함수 (3)파이프 라이브러리 함수 (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);

}

Page 16: Linux System Programming

Linux System Programming 16

명명된 파이프 (Named Pipe) (1)명명된 파이프 (Named Pipe) (1)

명명된 파이프 (Named Pipe) 비명명된 파이프의 문제점

첫째 , 파이프는 부무와 자식 프로세스와 같이 연관된 프로세스만이 접근 가능하다

둘째 , 파이프는 영구히 존재할 수 없다 – 파이프는 필요할 때에 만들어지고 파이프와 관계된 프로세스가 종료할 때에 소멸한다

시스템 전체에 대해 서비스를 제공하는 서버 (server) 를 개발하고자 할 때에 문제가 발생

명명된 파이프 또는 FIFO 비명명된 파이프와 같이 프로세스간의 통신 및 동기화 기능 지원 파일 시스템에서 특수 파일 형태로 영구 존재 리눅스 파일 이름을 부여하고 접근 허가 설정을 통해 모든

프로세스가 접근 가능 비명명된 파이프와 동일한 방법으로 시스템 호출을 사용하여 접근

Page 17: Linux System Programming

Linux System Programming 17

명명된 파이프 (Named Pipe) (2)명명된 파이프 (Named Pipe) (2)

명명된 파이프 (Named Pipe) 생성 : mknod 시스템 호출

Page 18: Linux System Programming

Linux System Programming 18

명명된 파이프 (Named Pipe) (3)명명된 파이프 (Named Pipe) (3)

명명된 파이프 (Named Pipe) 생성 : mknod 시스템 호출의 매개 변수

생성되는 파일 유형 : 파일 생성 허가 모드 :

Page 19: Linux System Programming

Linux System Programming 19

명명된 파이프 (Named Pipe) (4)명명된 파이프 (Named Pipe) (4)

예제 8-4 다음 그림과 같은 기능을 지원하는 파일 서버 /클라이언트 (ser

ver/client) 프로그램

Page 20: Linux System Programming

Linux System Programming 20

명명된 파이프 (Named Pipe) (5)명명된 파이프 (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

Page 21: Linux System Programming

Linux System Programming 21

명명된 파이프 (Named Pipe) (6)명명된 파이프 (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);

}

Page 22: Linux System Programming

Linux System Programming 22

명명된 파이프 (Named Pipe) (7)명명된 파이프 (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);

}

Page 23: Linux System Programming

Linux System Programming 23

명명된 파이프 (Named Pipe) (8)명명된 파이프 (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);

}

Page 24: Linux System Programming

Linux System Programming 24

명명된 파이프 (Named Pipe) (9)명명된 파이프 (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;

}

Page 25: Linux System Programming

Linux System Programming 25

예제 프로그램 (1)예제 프로그램 (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); }

Page 26: Linux System Programming

Linux System Programming 26

예제 프로그램 (2)예제 프로그램 (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);}

Page 27: Linux System Programming

Linux System Programming 27

예제 프로그램 (3)예제 프로그램 (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); }

Page 28: Linux System Programming

Linux System Programming 28

예제 프로그램 (4)예제 프로그램 (4)

fpout = popen("wc -l","w");

while (fgets(line, BUFSIZ, fpin) != (char *) NULL) if(line[0] == '\n') fputs(line,fpout);

fclose(fpin); pclose(fpout);}

Page 29: Linux System Programming

Linux System Programming 29

예제 프로그램 (5)예제 프로그램 (5)

예제 8-9: 미니 셀 (mini-shell) 프로그램 ex7-16.c 를 파이프 라인

기능이 가능하도록 수정하여라 교재의 프로그램 ‘ ex8-9.c’ 를 참조

Page 30: Linux System Programming

Linux System Programming 30

예제 프로그램 (6)예제 프로그램 (6)

예제 8-10: 숫자 맞추기 게임 프로그램 :

1. 두 개의 프로그램은 명명된 파이프를 통해 통신한다2. 첫번째 프로그램은 명명된 파이프 (FIFO) 를 생성하고 임의의

숫자를 난수로 발생한다3. 첫번째 프로그램은 두번째 프로그램은에서 FIFO 를 통하여 전송한

숫자가 정답과 비교하여 크면 ‘ H’, 작으면 ‘ L’, 같으면 ‘ E’이라는 메시지를 FIFO 를 통해 두번째 프로그램에 전송한다

4. 두번째 프로그램은 경기자가 추측하여 응답한 숫자를 FIFO 를 통하여 첫번째 프로그램으로 전송하고 , 그값이 크다 (H), 작다(L), 같다 (E) 와 같은 응답을 받아 화면에 출력하여 숫자를 맞출 때까지 반복한다

5. 두 개의 파이프를 생성하여 질문과 응답을 전달하는 통신 채널로 사용한다

Page 31: Linux System Programming

Linux System Programming 31

예제 프로그램 (7)예제 프로그램 (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); }

Page 32: Linux System Programming

Linux System Programming 32

예제 프로그램 (8)예제 프로그램 (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);}

Page 33: Linux System Programming

Linux System Programming 33

예제 프로그램 (9)예제 프로그램 (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); }

Page 34: Linux System Programming

Linux System Programming 34

예제 프로그램 (10)예제 프로그램 (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);}