26
9. 파이프 Unix 프로그래밍 실습 목포해양대 해양컴퓨터공학과 1

Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

9장. 파이프

Unix 프로그래밍 및 실습

목포해양대 해양컴퓨터공학과 1

Page 2: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

강의 내용

1절 개요

2절 이름 없는 파이프

3절 이름 있는 파이프

http://lily.mmu.ac.kr/lecture/13u2/ch09.pdf

책에 나온 내용 반드시 man으로 확인할 것!

UNIX, LINUX 등 시스템마다 차이가 있을 수

있음을 반드시 인식

목포해양대 해양컴퓨터공학과 2

Page 3: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

다중 입출력

키보드와 파이프, 소켓을 동시에 처리해야 하는

경우가 대부분

순차적으로 각 I/O를 확인하는 방식의 경우 해당

장치에서 읽을 내용이 없는 경우 입력이 올 때까지

대기(Blocking)

다중 입출력 처리 시나리오

하나 이상의 파일기술자 하나가 준비될 때까지 잠든다

깨어나서 순차적으로 준비된 파일 기술자 확인 후 처리

다시 반복

목포해양대 해양컴퓨터공학과 3

Page 4: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

select()

동기식 다중 입출력 메커니즘 제공

세 집합에 속한 fd들 중에 입출력 중 하나 이상의 fd가

가능하면 반환 / timeout까지 없는 경우 역시 반환

하나 이상의 fd에서 입출력이 가능할 수 있으므로 각 fd_set의

내용을 순차적으로 확인해야 함

#include <sys/time.h> #include <sys/types.h> #include <unistd.h> int select(int n, fd_set *readfds, fd_set, *writefds, fd_set *exceptfds, struct timeval *timeout); FD_CLR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set); FD_SET(int fd, fd_set *set); FD_ZERO(fd_set *set);

읽기가 준비되었는지

확인할 fd 집합

쓰기가 준비되었는지

확인할 fd 집합

예외 또는 대역외 자료(소켓만) 가

있는지 확인할 fd 집합

최대 대기 시간

목포해양대 해양컴퓨터공학과 4

Page 5: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

파이프 채팅 예제

두 개의 이름 있는 파이프를 이용한 채팅

프로그램

fifo 이름과 open 순서 유의

select 이용법 주목

lily.out cara.out

목포해양대 해양컴퓨터공학과 5

Page 6: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

lily.c (1)

1 /*******************************************************************************/

2 /* lily.c */

3 /* fifo 이름과 open 하는 순서에 유의할 것 ! */

4 /*******************************************************************************/

5 #include <stdio.h>

6 #include <stdlib.h>

7 #include <errno.h>

8 #include <unistd.h>

9 #include <sys/types.h>

10 #include <sys/stat.h>

11 #include <fcntl.h>

12 #include <string.h>

13

14 #define MSG_SIZE 1024

15

목포해양대 해양컴퓨터공학과 6

Page 7: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

lily.c (2)

16 int main(int argc, char *argv[])

17 {

18 char *fifo1 = "lily2cara";

19 char *fifo2 = "cara2lily";

20 char snd_buf[MSG_SIZE];

21 char rcv_buf[MSG_SIZE];

22 char msg_header[MSG_SIZE];

23 int hd_length;

24 int rfd;

25 int sfd;

26 fd_set master_set, read_set;

27 int rd_cnt;

28 if (argc != 2) {

29 printf("usage: %s user_name \n", argv[0]);

30 exit(1);

31 }

32 memset(msg_header, 0, MSG_SIZE);

33 sprintf(msg_header, "%s : ", argv[1]);

34 hd_length = strlen(msg_header);

목포해양대 해양컴퓨터공학과 7

Page 8: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

lily.c (3)

35 if (mkfifo(fifo1, 0666) == -1) {

36 if (errno != EEXIST) {

37 fprintf(stderr, "Error in mkfifo %s\n", fifo1);

38 exit(2);

39 }

40 }

41 if (mkfifo(fifo2, 0666) == -1) {

42 if (errno != EEXIST) {

43 fprintf(stderr, "Error in mkfifo %s\n", fifo2);

44 exit(3);

45 }

46 }

47 if ((rfd = open(fifo2, O_RDONLY)) < 0) {

48 fprintf(stderr, "Error in open %s\n", fifo2);

49 exit(4);

50 }

51 if ((sfd = open(fifo1, O_WRONLY)) < 0) { // blocking until open for reading

52 fprintf(stderr, "Error in open %s\n", fifo1);

53 exit(5);

54 }

목포해양대 해양컴퓨터공학과 8

Page 9: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

lily.c (4)

55 FD_ZERO(&master_set);

56 FD_SET(0, &master_set);

57 FD_SET(rfd, &master_set);

58 while (read_set = master_set, select(sfd+1, &read_set, NULL, NULL, NULL) > 0) { // sfd + 1

59 if (FD_ISSET(0, &read_set)) {

60 if ((rd_cnt = read(0, snd_buf, MSG_SIZE)) <= 0) {

61 fprintf(stderr, "Error in read from stdin\n");

62 exit(6);

63 }

64 else {

65 if (write(sfd, msg_header, hd_length) != hd_length) {

66 fprintf(stderr, "Error in write to fifo\n");

67 exit(7);

68 }

69 if (write(sfd, snd_buf, rd_cnt) != rd_cnt) {

70 fprintf(stderr, "Error in write to fifo\n");

71 exit(7);

72 }

73 }

74 }

목포해양대 해양컴퓨터공학과 9

Page 10: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

lily.c (5)

75 if (FD_ISSET(rfd, &read_set)) {

76 if ((rd_cnt = read(rfd, rcv_buf, MSG_SIZE)) <= 0) {

77 fprintf(stderr, "Error in read from fifo\n");

78 exit(8);

79 }

80 else {

81 if (write(1, rcv_buf, rd_cnt) != rd_cnt) {

82 fprintf(stderr, "Error in write to stdout\n");

83 exit(9);

84 }

85 }

86 }

87 }

88 }

목포해양대 해양컴퓨터공학과 10

Page 11: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

cara.c (1)

1 /*******************************************************************************/

2 /* cara.c */

3 /* fifo 이름과 open하는 순서에 유의할 것! */

4 /*******************************************************************************/

5

6 #include <stdio.h>

7 #include <stdlib.h>

8 #include <errno.h>

9 #include <unistd.h>

10 #include <sys/types.h>

11 #include <sys/stat.h>

12 #include <fcntl.h>

13 #include <string.h>

14

15 #define MSG_SIZE 1024

16

목포해양대 해양컴퓨터공학과 11

Page 12: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

cara.c (2)

17 int main(int argc, char *argv[])

18 {

19 char *fifo1 = "lily2cara";

20 char *fifo2 = "cara2lily";

21 char snd_buf[MSG_SIZE];

22 char rcv_buf[MSG_SIZE];

23 char msg_header[MSG_SIZE];

24 int hd_length;

25 int rfd;

26 int sfd;

27 fd_set master_set, read_set;

28 int rd_cnt;

29 if (argc != 2) {

30 printf("usage: %s user_name \n", argv[0]);

31 exit(1);

32 }

33 memset(msg_header, 0, MSG_SIZE);

34 sprintf(msg_header, "%s : ", argv[1]);

35 hd_length = strlen(msg_header);

목포해양대 해양컴퓨터공학과 12

Page 13: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

cara.c (3)

36 if (mkfifo(fifo1, 0666) == -1) {

37 if (errno != EEXIST) {

38 fprintf(stderr, "Error in mkfifo %s\n", fifo1);

39 exit(2);

40 }

41 }

42 if (mkfifo(fifo2, 0666) == -1) {

43 if (errno != EEXIST) {

44 fprintf(stderr, "Error in mkfifo %s\n", fifo2);

45 exit(3);

46 }

47 }

48 if ((sfd = open(fifo2, O_WRONLY)) < 0) { // blocking until open for reading

49 fprintf(stderr, "Error in open %s\n", fifo2);

50 exit(5);

51 }

52 if ((rfd = open(fifo1, O_RDONLY)) < 0) {

53 fprintf(stderr, "Error in open %s\n", fifo1);

54 exit(4);

55 }

목포해양대 해양컴퓨터공학과 13

Page 14: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

cara.c (4)

56 FD_ZERO(&master_set);

57 FD_SET(0, &master_set);

58 FD_SET(rfd, &master_set);

59 while (read_set = master_set, select(rfd+1, &read_set, NULL, NULL, NULL) > 0) { // rfd + 1

60 if (FD_ISSET(0, &read_set)) {

61 if ((rd_cnt = read(0, snd_buf, MSG_SIZE)) <= 0) {

62 fprintf(stderr, "Error in read from stdin\n");

63 exit(6);

64 }

65 else {

66 if (write(sfd, msg_header, hd_length) != hd_length) {

67 fprintf(stderr, "Error in write to fifo\n");

68 exit(7);

69 }

70 if (write(sfd, snd_buf, rd_cnt) != rd_cnt) {

71 fprintf(stderr, "Error in write to fifo\n");

72 exit(7);

73 }

74 }

75 }

목포해양대 해양컴퓨터공학과 14

Page 15: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

cara.c (5)

76 if (FD_ISSET(rfd, &read_set)) {

77 if ((rd_cnt = read(rfd, rcv_buf, MSG_SIZE)) <= 0) {

78 fprintf(stderr, "Error in read from fifo\n");

79 exit(8);

80 }

81 else {

82 if (write(1, rcv_buf, rd_cnt) != rd_cnt) {

83 fprintf(stderr, "Error in write to stdout\n");

84 exit(9);

85 }

86 }

87 }

88 }

89 }

목포해양대 해양컴퓨터공학과 15

Page 16: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

select 응용과 pselect

select를 이용한 이식성/정밀도 높은 sleep 구현 마이크로 초 단위 sleep 구현

pselect (POSIX select) man 으로 3가지 차이점 확인

timeval 대신 timespec 구조체 사용으로 나노초 단위 타이머 이용

timout 값 유지 – 재설정 필요 없음

sigmask로 시그널 차단

struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 500; select (0, NULL, NULL, NULL, &tv);

목포해양대 해양컴퓨터공학과 16

Page 17: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

과제 – 예제 확인

[예제 9-1], [예제 9-2], [예제 9-3], [예제 9-4], [예제 9-5] (각 10점)

과제 개요 (2줄 이상)

프로그램

실행화면 캡처

[예제 9-6], [예제 9-7] (각 10점)

파이프를 이용한 채팅 예제 (100점)

보고서 첫 장에 다음 표 작성

제출기한 : 12월 1일 자정

과제 완성 여부 (O, X) 비고

예제 9-1 (10) O

예제 9-2 (10) O

… O

예제 9-7 (10) X

목포해양대 해양컴퓨터공학과 17

Page 18: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 1 (1)

서버를 통한 1:1 채팅 (1000점)

내용 채팅

서버는 공통 FIFO(이름을 미리 정할 것!) 생성 후 대기

채팅 클라이언트는 자신이 데이터를 받을 FIFO 생성 후, 공통 FIFO에

접속하여 자신의 아이디(FIFO 이름) 전달

채팅 서버는 전달된 아이디로 개별 FIFO를 열고, 공통 FIFO 감시

채팅 클라이언트는 모든 메시지 앞에 자신의 이름을 붙여 공통 FIFO로

전달

채팅 서버는 공통 FIFO로 메시지가 들어오면 그 메시지를 상대방 FIFO로

전달

채팅 클라이언트는 사용자의 키보드 입력이 들어오면 아이디를 붙여

공통 FIFO로 보내고, 자신의 FIFO에 데이터가 들어오면 화면에 출력

목포해양대 해양컴퓨터공학과 18

Page 19: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 1 (2)

응용과제 #1 체크리스트

체크 리스트 완성 여부

(O, X) 비고

(서버) 1. FIFO 정상 생성

(서버) 2. 클라이언트 정상 접속 (id 확인 후, 개별 FIFO open ) – 서버 화면에 상태 메시지 출력

(서버) 3. 클라이언트 메시지 수신

(서버) 4. 상대방 클라이언트에게 메시지 전달

(클라이언트) 1. FIFO 정상 생성

(클라이언트) 2. 이미 알려진 서버 FIFO로 접속

(클라이언트) 3. 키보드 입력과 개별 FIFO 감시하여 처리

(채팅) 두 클라이언트 간 대화 확인 (화면 캡처 – 4장 이내)

목포해양대 해양컴퓨터공학과 19

Page 20: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 1 힌트(1)

client.c

42 if (mkfifo(my_id, 0666) == -1) {

43 fprintf(stderr, "Error in mkfifo %s\n", my_id);

44 exit(2);

45 }

46

47 if ((sfd = open(com_fifo, O_WRONLY)) < 0) {

48 fprintf(stderr, "Error in open %s\n", my_id);

49 exit(3);

50 }

51

52 write(sfd, my_id, ID_SIZE); // first message

53

54 if ((rfd = open(my_id, O_RDONLY)) < 0) {

55 fprintf(stderr, "Error in open %s\n", my_id);

56 exit(4);

57 }

58

59 FD_ZERO(&master_set);

목포해양대 해양컴퓨터공학과 20

Page 21: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 1 힌트(2)

server.c

33 if (mkfifo(rd_fifo, 0666) == -1) {

34 if (errno != EEXIST) {

35 fprintf(stderr, "Error in mkfifo %s\n", rd_fifo);

36 exit(1);

37 }

38 }

39

40 if ((rfd = open(rd_fifo, O_RDONLY)) < 0) {

41 fprintf(stderr, "Error in open %s\n", rd_fifo);

42 exit(2);

43 }

44

45 while ((rd_cnt = read(rfd, rcv_buf, MSG_SIZE)) > 0) {

46 write(1, rcv_buf, rd_cnt);

47

48 if (strlen(rcv_buf) <= ID_SIZE) { // new client

49 if ((sfd = open(rcv_buf, O_WRONLY)) < 0) {

목포해양대 해양컴퓨터공학과 21

Page 22: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 2 (1)

서버를 통한 다자간 채팅 (1000점)

내용

응용과제 1 기능

임의의 순간에 클라이언트 추가 가능 (클라이언트

수 제한이 없어야 함)

서버는 메시지를 보내온 클라이언트를 제외한

나머지 클라이언트에게 메시지 전달

클라이언트는 SIGINT가 들어오면 자신이 만든 FIFO

제거 후 종료

목포해양대 해양컴퓨터공학과 22

Page 23: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 2 (2)

과제 제출시 서버와 클라이언트 설계 내용,

프로그램 소스 및 동작에 대한 설명 반드시

포함

응용과제 #2 체크리스트

체크 리스트 완성 여부

(O, X) 비고

(서버) 1. 새로운 클라이언트 확인 후 리스트에 추가

(서버) 2. 메시지를 수신했을 때 송신자를 제외한 나머지 모든 클라이언트에게 전달하는지 여부

(클라이언트) SIGINT가 들어왔을 때 자신이 만든 FIFO 제거 후 종료 여부

(채팅) 4개 이상 클라이언트 간 대화 확인 (윈도우 전체 화면 캡처 – 4장 이내)

목포해양대 해양컴퓨터공학과 23

Page 24: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 2 (3)

참고도

Client

(id=abc)

Client

(id=def)

abc

def

com

Client

(id=xyz)

xyz

목포해양대 해양컴퓨터공학과 24

Page 25: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 3 (1)

서버를 통한 다자간 채팅 보완(1000점)

내용

응용과제 2 기능

임의의 순간에 클라이언트가 종료되더라도 나머지

클라이언트간 통신은 지속할 수 있도록 개선

클라이언트가 종료되면 해당 FIFO로 데이터를 보낼 수 없음

이때 발생하는 시그널을 이용하거나, 각 FIFO의 정상동작 여부를

확인하는 방법, 클라이언트가 종료될 때 반드시 서버에게

알리도록 하는 방법 등이 있음

여러 가지 방법 중 하나 또는 둘 이상을 구현하여 임의의 순간에

클라이언트가 들어오고 나갈 수 있도록 함

단, 클라이언트가 하나도 없는 경우 서버는 종료해도 무방함

목포해양대 해양컴퓨터공학과 25

Page 26: Unix 프로그래밍 및 실습 9장 파이프lily.mmu.ac.kr/lecture/14u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 및 실습 ... 다중 입출력 처리 시나리오

응용과제 3 (2)

과제 제출시 서버와 클라이언트 설계 내용,

프로그램 소스 및 동작에 대한 설명 반드시

포함

응용과제 #3 체크리스트

체크 리스트

완성 여부 (O, X)

비고

(서버) 1. 임의의 순간에 클라이언트 추가, 삭제 가능 여부

(서버) 2. 클라이언트가 모두 나갈 때까지 정상 동작 여부

(채팅) 4개 이상 클라이언트 간 대화 및 임의의 순간에 추가, 탈퇴 확인 (윈도우 전체 화면 캡처 – 8장 이내)

목포해양대 해양컴퓨터공학과 26