1 / 39

Linux System Programming

Linux System Programming. Lecture #9 – 메시지 큐 (Message Queue). 동일한 플랫폼 상에서 유사하게 구현되어 ICP 도구로 별도 분류하기도 함. IPC(Inter-Process Communication) (1). 프로세스 통신 도구 (IPC Facilites) : 비동기적으로 동작하는 프로세스간의 통신을 위하여 운영체제가 제공하는 도구 종류 : Signal( 신호 ) Pipe( 파이프 ) Message Queue( 메시지 큐 )

addison
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 #9 –메시지 큐(Message Queue)

  2. 동일한 플랫폼 상에서 유사하게 구현되어 ICP 도구로 별도 분류하기도 함 IPC(Inter-Process Communication) (1) • 프로세스 통신 도구(IPC Facilites) : • 비동기적으로 동작하는 프로세스간의 통신을 위하여 운영체제가 제공하는 도구 • 종류: • Signal(신호) • Pipe(파이프) • Message Queue(메시지 큐) • Semaphore(세마포어) • Shared Memory(공유 메모리) • Socket(소켓) Linux System Programming

  3. IPC(Inter-Process Communication) (2) • 프로세스 통신 도구 (IPC Facilites): • 세마포어(Semaphore) • 프로세스 동기화와 자원 관리에 사용 • 프로세스간의 상호배제 문제 해결에 사용 • 공유 메모리(Shared Memory) • 가장 빠른 프로세스 통신 도구 • 하나 이상의 프로세스에 부착하여 서로 공유하여 접근 가능 • 프로세스간의 공유 메모리 접근을 위해 동기화가 필요 • 메시지 큐(Message Queue) • 프로세스들간에 이산적인 양의 데이터 송수신을 위해 사용 • 전송할 데이터를 메시지 형태로 생성하여 전달하고 메시지 수신을 통해 데이터 수신이 가능 • 인터넷 메일 서비스와 개념이 유사 Linux System Programming

  4. IPC(Inter-Process Communication) (3) • IPC와 관련한 시스템 호출 함수: • IPC 시스템 호출 함수: Linux System Programming

  5. IPC(Inter-Process Communication) (4) • IPC와 관련한 시스템 호출 함수: • get 시스템 호출 • 파일 열기 시스템 호출 open과 유사 • 새롭게 통신 도구를 생성하거나 이미 생성된 통신 도구에 대한 id를 반환하여 접근 가능하게 함 • 반환된 id는 파일 디스크립터와 비슷하게 동작 • 접근 허가 또한 파일 접근 허가와 비슷하게 규정 • ctl 시스템 호출 • 통신 도구에 관한 상태 정보 읽기 • 몇몇 상태 정보(소유자, 그룹, 접근 허가 등)에 대한 변경 • 통신 도구의 제거 기능 • op 시스템 호출 • 프로세스간의 데이터 전송을 실행 • 파일 시스템 호출 read/write와 유사 • Shmat는 파일의 open과 유사하고, shmdt는 파일의 close와 유사 Linux System Programming

  6. key_t char device Inode # of file IPC(Inter-Process Communication) (5) • IPC 도구 식별자: • IPC 도구 식별자 – IPC key • 파일을 식별하기 위해 파일 이름을 사용하듯이 IPC 객체를 식별하기 위해 사용하는 정수형 숫자 • 프로세스들은 IPC key를 이용하여 IPC 자원을 공유 • 자료형: key_t (<sys/types.h>에 정의) • IPC key 변환 시스템 호출 – ftok(file_to_key) • IPC 도구의 공유를 편리하게 지원하기 위해 파일 경로명과 식별자를 IPC 도구에 부여하고, 이를 IPC key 값으로 변환하는 시스템 호출 Linux System Programming

  7. IPC(Inter-Process Communication) (6) • IPC 도구 식별자: • IPC key 변환 시스템 호출 – ftok(file_to_key) Linux System Programming

  8. IPC(Inter-Process Communication) (7) • IPC 도구의 상태 자료 구조: • IPC 도구의 상태 구조 • 생성된 IPC 객체에 대한 상태 정보를 저장하는 구조체 • IPC 도구 유형별로 별도의 상태 구조체를 지원하나 다음의 접근 허가 구조를 공통으로 포함한다 • IPC 도구의 접근 허가 구조: struct ipc_perm • 파일의 접근 허가와 유사한 기능을 지원 • 접근 모드에서 실행 모드는 무의미함 Linux System Programming

  9. IPC(Inter-Process Communication) (8) • IPC 도구의 상태 자료 구조: • IPC 도구 테이블 • IPC 도구 유형별로 생성된 IPC 객체를 관리하기 위해 운영체제가 유지하는 테이블 • IPC 도구 유형별로 각각의 테이블을 유지 • 파일 테이블과 유사한 개념 Linux System Programming

  10. IPC(Inter-Process Communication) (9) • IPC 도구 관리 명령: • ipcs 명령 • 현재 사용중인 IPC 도구들의 상태(status)를 보여주는 명령 • IPC 타입, 사용자 ID, key 값 그리고 접근 허가 등을 볼 수 있음 • 옵션을 사용하여 지정된 유형의 IPC 도구 상태 정보만을 접근 가능 • -q : 메시지 큐, -m : 공유 메모리, -s : 세마포어 • ipcrm 명령 • IPC 객체를 제거하는 명령 • IPC 도구 유형 및 key 값을 지정하는 원하는 IPC 객체를 제거 Linux System Programming

  11. 메시지 큐(Message Queue) (1) • 메시지 큐: • 프로세스간에 이산적인 데이터를 메시지 형태로 전송하는 통신 도구 • 파이프와 같이 FIFO 타입의 데이터 전송을 지원 • 메시지는 메시지와 바이트(byte)들의 모임으로 구성 • 메시지 유형은 정수값으로 여러가지 메시지 형태에 id를 부여하여 구별하기 위해 사용 • 바이트 모임은 전송하는 데이터를 의미하는 것으로 문자, 그림 또는 일련의 구조체 데이터 등을 전송하기 위햇 사용 • 관련 시스템 호출 함수 • msgget() –메시지 큐를 생성 • msgsnd()/msgrcv() –메시지 전송 및 수신 • msgctl() –메시지 큐 제어 Linux System Programming

  12. 메시지 큐(Message Queue) (2) • 메시지 큐의 구조: • 메시지 큐의 상태 구조체 : msgid_ds • 메시지 큐 객체의 상태 정보를 저장하는 구조체 • 하나의 메시지 큐가 생성되면 하나의 msgid_ds 구조체가 생성 Linux System Programming

  13. 메시지 큐(Message Queue) (3) • 메시지 큐의 동작: • 전송 프로세스가 전송할 데이터를 메시지 형태로 만들어 메시지를 전송하면 전송된 메시지는 메시지 큐의 마지막에 연결된다 • 수신 프로세스는 메시지 큐에 존재하는 메시지를 선택적으로 수신할 수 있다. • 수신 프로세스에서는 메시지를 수신할 때에 다음의 수신 정책 중에 하나를 지정하여야 한다. • 메시지 큐에서 첫번째 메시지 • 메시지 큐에서 지정된 타입의 첫번째 메시지 • 메시지 큐에 있는 타입들의 범위들로 부터 첫번째 메시지 Linux System Programming

  14. 메시지 큐(Message Queue) (4) • 메시지 큐의 생성: msgget • msgget –메시지 큐 생성 시스템 호출 • 주어진 key를 갖는 메시지 큐가 존재하면 메시지 큐의 id를 반환하고, 그렇지 않으면 새롭게 메시지 큐를 생성하고 id를 반환 Linux System Programming

  15. 메시지 큐(Message Queue) (5) • 메시지 큐의 생성: msgget • 메시지 큐 구조체: msqid_ds Linux System Programming

  16. 메시지 큐(Message Queue) (6) • 메시지 큐의 생성: msgget • 메시지 큐 구조체의 초기값 Linux System Programming

  17. 메시지 큐(Message Queue) (7) • 메시지 큐의 생성: msgget • msgget 시스템 호출의 flag 옵션 Linux System Programming

  18. 메시지 큐(Message Queue) (8) • 메시지 큐의 제어: msgctl • msgctl - 메시지 큐 제어 시스템 호출 • 메시지 큐의 상태를 질의하거나 상태 정보를 변경, 또는 메시지 큐를 제거하는 기능을 지원 Linux System Programming

  19. 메시지 큐(Message Queue) (9) • 메시지 큐의 제어: msgctl • msgctl 시스템 호출의 명령어 Linux System Programming

  20. 메시지 큐(Message Queue) (10) • msgctl 시스템 호출의 사용 예 • 메시지 큐 관련 자료 구조 선언 • 메시지 큐의 제거 • 메시지 큐의 소유자 변경 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msqid; struct msqid_ds ds; msgctl(msqid, IPC_RMID, (struct msqid_ds *)0); msgctl(msqid, IPC_STAT, &ds); ds.msg_perm.uid = 51; msgctl(msqid, IPC_SET, &ds); Linux System Programming

  21. 메시지 큐(Message Queue) (11) • msgctl 시스템 호출의 사용 예 • 메시지 큐의 접근 허가 변경 • 메시지 큐의 메시지 크기 변경 msgctl(msqid, IPC_STAT, &ds); ds.msg_perm.mode = 0660; msgctl(msqid, IPC_SET, &ds); msgctl(msqid, IPC_STAT, &ds); ds.msg_qbytes = 5000; msgctl(msqid, IPC_SET, &ds); Linux System Programming

  22. 메시지 큐(Message Queue) (12) • 메시지 큐의 연산: msgsnd, msgrcv • 메시지 구조체 : • 메시지 유형은 전송되는 여러가지 유형의 메시지 형태를 분류하여 지정 • 메시지 텍스트는 전송하는 데이터를 저장 • 메시지 텍스트의 크기는 최소 0에서 최대 64 KB 이내이며, 묵시적으로 2048 바이트로 사용 #include <sys/msg.h> struct msgbuf { long mtype; /* 메시지 유형 */ char mtext[1]; /* 메지시 텍스트 */ } Linux System Programming

  23. 메시지 큐(Message Queue) (13) • 메시지 큐의 연산: msgsnd, msgrcv • 메시지 송신 시스템 호출 : msgsnd Linux System Programming

  24. 메시지 큐(Message Queue) (13) • 메시지 큐의 연산: msgsnd, msgrcv • msgsnd 시스템 호출에 의한 메시지 큐 구조체 변경 Linux System Programming

  25. 메시지 큐(Message Queue) (14) • 메시지 큐의 연산: msgsnd, msgrcv • 메시지 수신 시스템 호출 : msgrcv Linux System Programming

  26. 메시지 큐(Message Queue) (15) • 메시지 큐의 연산: msgsnd, msgrcv • msgrcv 시스템 호출에서의 메시지 타입 지정 • msgrcv 시스템 호출에 의한 메시지 큐 구조체 변경 Linux System Programming

  27. 예제 프로그램 (1) • 예제 9-1 • 하나의 메시지를 전송하고 수신하는 프로그램을 작성하여라 // file name : ex9-1a.c // #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> struct { long t; char a[60]; } x = {11L,"hello"}; main() { int mid; mid = msgget(11L,IPC_CREAT| 0666); msgsnd(mid,&x,strlen(x.a)+1,0); sleep(60); msgctl(mid,IPC_RMID,0); } Linux System Programming

  28. 예제 프로그램 (2) // file name : ex9-1b.c // #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> struct { long t; char a[60]; } x ; main() { int mid,rtn; mid = msgget(11L,0); rtn=msgrcv(mid,&x,60,0L,0); printf("rtn=%d type=%d text=%s\n",rtn,x.t,x.a); } Linux System Programming

  29. 예제 프로그램 (3) • 예제 9-2 • 예제 9-1을 개선하여 여러 개의 메시지를 송수신하는 프로그램을 작성하여라. // file name : ex9-2a.c // #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #define MAX_SEND_SZ 30 #define DONE 99L main() { void perror(); key_t key; int mid; static struct { long mtype; char mtext[MAX_SEND_SZ]; } buf; Linux System Programming

  30. 예제 프로그램 (4) static char *string[3] = { "hello", "how are you", "good-bye"}; int i,rtn; if((key= ftok(".",'a'))==-1) { perror("Can\'t form key"); exit(1); } mid = msgget(key,IPC_CREAT| 0660); if(mid == -1) { perror("Sender can not make msg queue!"); exit(2); } Linux System Programming

  31. 예제 프로그램 (5) buf.mtype = 1L; for(i=0;i<3;i++) { strcpy(buf.mtext,string[i]); if(msgsnd(mid,&buf,strlen(buf.mtext)+1,0)==-1) { perror("Sender can not msgsnd!"); exit(3); } } rtn = msgrcv(mid,&buf,MAX_SEND_SZ,DONE,0); if(rtn == -1) { perror("Sender can not msgrcv"); exit(4); } msgctl(mid,IPC_RMID,0); } Linux System Programming

  32. 예제 프로그램 (6) // file name : ex9-2b.c // #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #define MAX_RECV_SZ 60 #define FIFO 0L #define ZERO_LEN 0 #define DONE 99L static struct { long mtype; char mtext[MAX_RECV_SZ]; } buf; key_t key; int mid; int rtn; Linux System Programming

  33. 예제 프로그램 (7) main(int argv,char *argc[]) { void perror(); if((key= ftok(".",'a'))==-1) { perror("Can\'t form key"); exit(1); } mid = msgget(key,0); if(mid == -1) { perror("Receiver can not access msg queue!"); exit(2); } while(1) { rtn = msgrcv(mid,&buf,MAX_RECV_SZ,FIFO,0); printf("rtn=%d buf.mtype=%ld buf.mtext=%s\n", rtn,buf.mtype,buf.mtext); if(!strcmp(buf.mtext,"good-bye")) break; } buf.mtype = DONE; msgsnd(mid,&buf,ZERO_LEN,0); } Linux System Programming

  34. 예제 프로그램 (8) • 예제 9-3 • 메시지 송신 프로그램가 키보드 입력을 메시지로 만들어 여러 개의 수신 프로그램에 전달하는 프로그램을 작성하여라. • 송신 프로그램은 fork()/exec() 시스템 호출을 통하여 수신 프로세스를 생성하고, 수신 프로세스는 수신된 메시지를 표준 출력으로 출력하도록 한다. // file name : ex9-3a.c // #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #define MAX_SZ 80 #define NCHILD 3 Linux System Programming

  35. 예제 프로그램 (9) #define WAIT_SOLE_USE(MSGQID) { \ int still_active = NCHILD; \ int i; \ long s_pid; \ s_pid = getpid(); \ while(still_active) { for(i=0;i<NCHILD;i++) \ if(msgrcv(MSGQID,&buf,MAX_SZ,s_pid,IPC_NOWAIT) != -1) \ if(!strncmp(buf.mtext,"DONE",4)) still_active--; \ sleep(2); \ } \ } main() { void perror(); key_t ftok(); int msgqid; struct { long mtype; char mtext[MAX_SZ]; } buf; Linux System Programming

  36. 예제 프로그램 (10) int msg_length; static char qid_evar[40]; static char *envp[2] = { qid_evar }; int this_fork, child; long r_pid[NCHILD]; char child_name[20]; int eof = 0; if((msgqid = msgget(IPC_PRIVATE,IPC_CREAT | 0660)) == -1) { perror("Sender can't make message queue!"); exit(1); } sprintf(qid_evar,"MQID=%d",msgqid); for(child=0;child<NCHILD;child++) { this_fork = fork(); if(this_fork == -1) { perror("fork failed"); exit(2); } else if(this_fork == 0) { sprintf(child_name,"mwall_r%d",child); execle("ex9-3b",child_name,0,envp); perror("exec failed"); exit(3); } else r_pid[child] = (long) this_fork; } Linux System Programming

  37. 예제 프로그램 (11) setbuf(stdout,(char *) 0); while(1) { fprintf(stdout, "Enter message to be sent to all receivers:"); if(gets(buf.mtext) == (char *) 0) { fprintf(stdout,"\n"); eof++; strcpy(buf.mtext,"EOF"); } msg_length = strlen(buf.mtext) +1; for(child=0;child<NCHILD;child++) { buf.mtype = r_pid[child]; if(msgsnd(msgqid,&buf,msg_length,0) == -1) { perror("Producer msgsnd error"); exit(4); } } if(eof) break; sleep(1); } WAIT_SOLE_USE(msgqid); msgctl(msgqid,IPC_RMID,0); } Linux System Programming

  38. 예제 프로그램 (12) // file name : ex9-3a.c // #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #define MAX_SZ 80 main(int argc, char *argv[]) { void perror(); char *getenv(); long pid; char *valuep; int msgqid; struct { long mtype; char mtext[MAX_SZ]; } buf; Linux System Programming

  39. 예제 프로그램 (13) pid = (long) getpid(); if((valuep = getenv("MQID")) == NULL) { fprintf(stderr,"%s:can't get env MQID\n",argv[0]); exit(1); } else sscanf(valuep,"%d",&msgqid); while(1) { msgrcv(msgqid,&buf,MAX_SZ,pid,MSG_NOERROR); printf("%s received '%s'\n",argv[0],buf.mtext); if(!strcmp(buf.mtext,"EOF")) break; } buf.mtype = (long) getppid(); strcpy(buf.mtext,"DONE"); if(msgsnd(msgqid,&buf,strlen(buf.mtext),0) == -1) { fprintf(stderr,"%s:msgsnd error\n",argv[0]); exit(2); } exit(0); } Linux System Programming

More Related