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

1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

9장. 파이프 Unix 프로그래밍 및 실습

목포해양대

해양컴퓨터공학과

1

Page 2: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

강의 내용

• 1절 개요

• 2절 이름 없는 파이프

• 3절 이름 있는 파이프

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

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

• UNIX, LINUX 등 시스템마다 차이가 있을 수 있음을 반드시 인식

목포해양대

해양컴퓨터공학과

2

Page 3: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

기본실습 #1

• [예제 9-1] ~ [예제 9-7] (각 10점)

• 과제 개요 (2줄 이상)

• 프로그램

• 실행화면 캡처

• 보고서 첫 장에 다음 표 작성

목포해양대

해양컴퓨터공학과

3

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

예제 9-1 (10) O

예제 9-2 (10) O

… O

예제 9-7 (10) X

Page 4: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

다중 입출력

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

대부분

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

읽을 내용이 없는 경우 입력이 올 때까지 대기(Blocking)

• 다중 입출력 처리 시나리오

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

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

• 다시 반복

목포해양대

해양컴퓨터공학과

4

Page 5: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

select()

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

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

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

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

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

목포해양대

해양컴퓨터공학과

5

#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 집합

최대 대기 시간

Page 6: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

파이프 채팅 예제

• 두 개의 이름 있는 파이프를 이용한 채팅 프로그램

• fifo 이름과 open 순서 유의

• select 이용법 주목

목포해양대

해양컴퓨터공학과

6

lily.out cara.out

Page 7: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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

목포해양대

해양컴퓨터공학과

7

Page 8: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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);

목포해양대

해양컴퓨터공학과

8

Page 9: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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 }

목포해양대

해양컴퓨터공학과

9

Page 10: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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 }

목포해양대

해양컴퓨터공학과

10

Page 11: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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 }

목포해양대

해양컴퓨터공학과

11

Page 12: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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

목포해양대

해양컴퓨터공학과

12

Page 13: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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);

목포해양대

해양컴퓨터공학과

13

Page 14: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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 }

목포해양대

해양컴퓨터공학과

14

Page 15: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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 }

목포해양대

해양컴퓨터공학과

15

Page 16: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/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 }

목포해양대

해양컴퓨터공학과

16

Page 17: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

기본실습 #2

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

목포해양대

해양컴퓨터공학과

17

Page 18: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

select 응용과 pselect

• select를 이용한 이식성/정밀도 높은 sleep 구현

• 마이크로 초 단위 sleep 구현

• pselect (POSIX select)

• man 으로 3가지 차이점 확인

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

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

• sigmask로 시그널 차단

목포해양대

해양컴퓨터공학과

18

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

Page 19: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 1 (1)

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

• 내용 채팅

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

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

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

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

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

FIFO로 전달

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

FIFO로 전달

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

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

화면에 출력

목포해양대

해양컴퓨터공학과

19

Page 20: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 1 (2)

• 응용과제 #1 체크리스트

목포해양대

해양컴퓨터공학과

20

체크 리스트 완성 여부

(O, X) 비고

(서버) 1. FIFO 정상 생성

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

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

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

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

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

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

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

Page 21: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 1 힌트(1)

• client.c

목포해양대

해양컴퓨터공학과

21

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);

Page 22: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 1 힌트(2)

• server.c

목포해양대

해양컴퓨터공학과

22

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) {

Page 23: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 2 (1)

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

• 내용

• 응용과제 1 기능

• 임의의 순간에 클라이언트 추가 가능 (클라이언트 수 제한이

없어야 함)

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

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

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

종료 목포해양대

해양컴퓨터공학과

23

Page 24: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 2 (2)

• 과제 제출시 서버와 클라이언트 설계 내용, 프로그램 소스 및

동작에 대한 설명 반드시 포함

• 응용과제 #2 체크리스트

목포해양대

해양컴퓨터공학과

24

체크 리스트 완성 여부

(O, X) 비고

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

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

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

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

Page 25: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 2 (3)

• 참고도

목포해양대

해양컴퓨터공학과

25

Client (id=abc)

Client (id=def)

abc

def

com

Client (id=xyz)

xyz

Page 26: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 3 (1)

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

• 내용

• 응용과제 2 기능

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

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

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

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

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

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

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

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

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

목포해양대

해양컴퓨터공학과

26

Page 27: 1장. 유닉스 시스템 프로그래밍 개요lily.mmu.ac.kr/lecture/17u2/UNIX2_09.pdf · 9장. 파이프 Unix 프로그래밍 ... • 다중 입출력 처리 시나리오 • 하나

응용과제 3 (2)

• 과제 제출시 서버와 클라이언트 설계 내용, 프로그램 소스 및

동작에 대한 설명 반드시 포함

• 응용과제 #3 체크리스트

목포해양대

해양컴퓨터공학과

27

체크 리스트 완성 여부

(O, X) 비고

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

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

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