<4D F736F F F696E74202D FBDC3BDBAC5DB56C0C720C7C1B7CEBCBCBDBAB0A320C5EBBDC5205BC8A3C8AF20B8F0B5E55D>

Similar documents
2009년 상반기 사업계획

고급 IPC 설비

Chap06(Interprocess Communication).PDF

Microsoft PowerPoint - UnixNetProg3rd_08_완.ppt [호환 모드]

고급 IPC 설비

메시지큐를이용한 IPC 프로그램구현과제보고서 1. 과제의목적 1 리눅스가지원하는프로세스간통신방식중다수의프로세스사이에구조화된데이터블럭, 즉메시지를전달하는데주로사용되는메시지큐방식에대하여무엇인지, 어떻게사용하는지공부한다. 2 공부한내용을점검하기위해기작성된 epda 프로세스관

운영체제 실습 - Introduction -

슬라이드 1

Microsoft PowerPoint - ch09_파이프 [호환 모드]

2009년 상반기 사업계획

2009년 상반기 사업계획

<4D F736F F F696E74202D FC7C1B7CEBCBCBDBA20BBFDBCBAB0FA20BDC7C7E0205BC8A3C8AF20B8F0B5E55D>

2009년 상반기 사업계획

<4D F736F F F696E74202D FB8DEB8F0B8AE20B8C5C7CE205BC8A3C8AF20B8F0B5E55D>

Abstract View of System Components

좀비프로세스 2

2009년 상반기 사업계획

제1장 Unix란 무엇인가?

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

K&R2 Reference Manual 번역본

ABC 11장

슬라이드 1

Microsoft PowerPoint - all_CDSP_2(2009).ppt [호환 모드]

1장. 유닉스 시스템 프로그래밍 개요

Microsoft PowerPoint - chap03-변수와데이터형.pptx

10.

Chapter #01 Subject

The Pocket Guide to TCP/IP Sockets: C Version

6주차.key

chap 5: Trees

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

11장 포인터

제1장 Unix란 무엇인가?

vi 사용법

Microsoft PowerPoint - 09-Pipe

PowerPoint 프레젠테이션

API 매뉴얼

Microsoft PowerPoint - Lecture_Note_7.ppt [Compatibility Mode]

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

OCW_C언어 기초

이번장에서학습할내용 동적메모리란? malloc() 와 calloc() 연결리스트 파일을이용하면보다많은데이터를유용하고지속적으로사용및관리할수있습니다. 2

untitled

Chapter 4. LISTS

Microsoft PowerPoint - chap05-제어문.pptx

슬라이드 1

chap7.key

OCW_C언어 기초

제1장 Unix란 무엇인가?

Microsoft PowerPoint - chap10-함수의활용.pptx

금오공대 컴퓨터공학전공 강의자료

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

The Pocket Guide to TCP/IP Sockets: C Version

Microsoft Word - Network Programming_NewVersion_01_.docx

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CC0E7B0EDB0FCB8AE5C53746F636B5F4D616E D656E74732E637070>

Microsoft PowerPoint - Lecture_Note_5.ppt [Compatibility Mode]

PowerPoint 프레젠테이션

Microsoft PowerPoint - ch07 - 포인터 pm0415

Microsoft PowerPoint - 04-UDP Programming.ppt

PowerPoint Presentation


03장.스택.key

제9장 프로세스 제어

untitled

학습목차 2.1 다차원배열이란 차원배열의주소와값의참조

PowerPoint 프레젠테이션

/chroot/lib/ /chroot/etc/

3. 다음장에나오는 sigprocmask 함수의설명을참고하여다음프로그램의출력물과그출력물이화면이표시되는시점을예측하세요. ( 힌트 : 각줄이표시되는시점은다음 4 가지중하나. (1) 프로그램수행직후, (2) kill 명령실행직후, (3) 15 #include <signal.

Microsoft PowerPoint - C프로그래밍-chap03.ppt [호환 모드]

Microsoft PowerPoint - 10_Process

11장 포인터

비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2

PowerPoint 프레젠테이션

Microsoft PowerPoint - chap06-2pointer.ppt

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

본 강의에 들어가기 전

Lab 3. 실습문제 (Single linked list)_해답.hwp

Microsoft PowerPoint - 13 ¼ÒÄÏÀ» ÀÌ¿ëÇÑ Åë½Å 2.ppt

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

Microsoft PowerPoint - SP6장-시그널.ppt [호환 모드]

제 14 장포인터활용 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

The Pocket Guide to TCP/IP Sockets: C Version

PowerPoint 프레젠테이션

Microsoft PowerPoint - [2009] 02.pptx

Microsoft PowerPoint - C++ 5 .pptx

<4D F736F F F696E74202D BDC3B1D7B3CEB0FA20BDC3B1D7B3CE20C3B3B8AE2E707074>

Microsoft PowerPoint - chap11-포인터의활용.pptx

Frama-C/JESSIS 사용법 소개

BMP 파일 처리

3. 1 포인터란 3. 2 포인터변수의선언과사용 3. 3 다차원포인터변수의선언과사용 3. 4 주소의가감산 3. 5 함수포인터

Microsoft PowerPoint - 12 ¼ÒÄÏÀ» ÀÌ¿ëÇÑ Åë½Å 1.ppt

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾

UI TASK & KEY EVENT

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt

Microsoft PowerPoint - chap12-고급기능.pptx

PowerPoint 프레젠테이션

슬라이드 1

제12장 파일 입출력

Chapter_06

Transcription:

학습목표 유닉스시스템V에서제공하는 IPC기법을이해한다. 메시지큐를이용해통신프로그램을작성할수있다. 공유메모리를이용해통신프로그램을작성할수있다. 세마포어를이용한 IPC기법을배운다. 시스템 V 의프로세스간통신 IT CookBook, 유닉스시스템프로그래밍 2/42 목차 시스템 V IPC 기초 시스템 V IPC 관련명령 메시지큐 공유메모리 세마포어 시스템 V IPC 기초 [1] 시스템 V IPC 시스템 V 계열유닉스에서개발해제공하는프로세스간통신방법 메시지큐, 공유메모리, 세마포어 공통요소 시스템 V IPC 를사용하기위해서는 IPC 객체를생성해야함. IPC 객체를생성하기위해공통적으로사용하는기본요소는키와식별자 키생성 키로 IPC_PRIVATE 지정 ftok 함수로키생성 key_t ftok(const char *path, int id); 인자로파일시스템에이미존재하는임의의파일의경로명과 1~255 사이의번호지정 키의구조에서 id(8 비트 ) 에인자로지정한번호저장. 번호에 0 은지정하지않는다. 3/42 4/42

시스템 V IPC 기초 [2] IPC 공통구조체 IPC 객체를생성하면 IPC 공통구조체가정의된다. 시스템 V IPC 관련명령 [1] 시스템 V IPC 정보검색 : ipcs 명령 시스템 V IPC 의정보를검색하고현재상태확인 struct ipc_perm { uid_t uid; gid_t gid; uid_t cuid; gid_t cgid; mode_t mode; uint_t seq; key_t key; int pad[4]; uid, gid : 구조체소유자ID 및소유그룹ID cuid, cgid : 구조체를생성한사용자ID, 그룹ID mode : 구조체에대한접근권한 seq : 슬롯의일련번호 key : 키값 pad : 향후사용을위해예약된영역 ipcs [ aabcijmopqstz] [ D mtype] -m : 공유메모리에관한정보만검색 -q : 메시지큐에관한정보만검색 -s : 세마포어에관한정보만검색 -a : -b, -c, -o, -p, -t 옵션으로검색하는항목모두출력 -A : 전체항목을모드검색 -b : 각방법의최댓값검색 -c : IPC 객체를생성한사용자의로그인명과그룹명검색 -D mtype : 메시지큐에서 mtype 으로지정한메시지만검색 -i : 공유메모리세그먼트에연결된 ISM 의개수출력 -J : IPC 객체생성자의프로젝트명출력 -o : 현재사용되고있는정보출력 -p : PID 정보출력 -t : 시간정보출력 5/42 6/42 시스템 V IPC 관련명령 [2] IPCS 명령사용예 현재동작중인 IPC 객체가하나도없는경우 # ipcs IPC status from <running system> as of 2009 년 2 월 18 일수요일오전 09 시 36 분 41 초 T ID KEY MODE OWNER GROUP Shared Memory: Semaphores: -A 옵션지정시 : 모든항목출력 # ipcs A IPC status from <running system> as of 2009년 2월 18일수요일오전 10시 36분 41초 T ID KEY MODE OWNER GROUP CREATOR CGROUP CBYTES QNUM QBYTES LSPID LRPID STIME RTIME CTIME PROJECT T ID KEY MODE OWNER GROUP CREATOR CGROUP NATTCH SEGSZ CPID LPID ATIME DTIME CTIME ISMATTCH PROJECT Shared Memory: T ID KEY MODE OWNER GROUP CREATOR CGROUP NSEMS OTIME CTIME PROJECT Semaphores: 7/42 시스템 V IPC 관련명령 [3] 시스템 V IPC 정보삭제 : ipcrm ipcrm [ m shmid] [ q msqid] [ s semid] [ M shmkey] [ Q msgkey] [ S emkey] -m shmid : 공유메모리삭제 -q msqid : 메시지큐삭제 -s semid : 세마포어삭제 -M shmkey : shmkey 로지정한공유메모리삭제 -Q msgkey : msgkey 로지정한공유메모리삭제 -S semkey : semkey 로지정한공유메모리삭제 8/42

메시지큐 [1] 메시지큐 파이프와유사하나파이프는스트림기반으로동작하고메시지큐는메시지단위로동작 각메시지의최대크기는제한되어있음 각메시지에는메시지유형이있어수신프로세스는어떤유형의메시지를받을것인지선택가능 메시지큐생성 : msgget(2) #include <sys/msg.h> int msgget(key_t key, int msgflg); key : IPC_PRIVATE 또는 ftok 로생성한키값 msgflg : 플래그와접근권한지정 IPC_CREAT : 새로운키면식별자를새로생성 IPC_EXCL : 이미존재하는키면오류발생 메시지큐식별자를리턴 (msqid_ds 구조체 ) 메시지큐 [2] msqid_ds 구조체 struct msqid_ds { struct ipc_perm msg_perm; struct msg *msg_first; struct msg *msg_last; msglen_t msg_cbytes; msgqnum_t msg_qnum; msglen_t msg_qbytes; pid_t msg_lspid; pid_t msg_lrpid; time_t msg_stime; int32_t msg_pad1; time_t msg_rtime; int32_t msg_pad2; time_t msg_ctime; int32_t msg_pad3; short msg_cv; short msg_qnum_cv; long msg_pad4[3]; msg_perm: IPC공통구조체 msg_first: 첫번째메시지에대한포인터 msg_last: 마지막메시지에대한포인터 msg_cbytes: 현재메시지큐에있는총바이트수 msg_qnum: 메시지큐에있는메시지개수 msg_qbytes: 메시지큐의최대크기 msg_lspid: 마지막으로메시지를보낸프로세스ID msg_lrpid: 마지막으로메시지를읽은프로세스ID msg_stime: 마지막으로메시지를보낸시각 msg_rtime: 마지막으로메시지를읽은시각 msg_ctime: 마지막으로메시지큐의권한변경시각 msg_pad1,2,3: 예비공간 9/42 10/42 메시지큐 [3] [ 예제 10-1] 메시지큐생성및메시지전송하기 ex10_1.c 메시지전송 : msgsnd(2) #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msqid : 메시지큐식별자 msgp : 메시지버퍼주소 msgsz : 메시지버퍼크기 msgflg : 블록모드 (0)/ 비블록모드 (IPC_NOWAIT) 메시지버퍼구조체 struct msqbuf { long mtype; char mtext[1]; mtype : 메시지유형으로양수를지정 mtext : 메시지내용저장 msgsz, int msgflg); 06 struct mymsgbuf { 07 long mtype; 08 char mtext[80]; 메시지버퍼정의 09 10 11 int main(void) { 12 key_t key; 13 int msgid; 14 struct mymsgbuf mesg; 15 16 key = ftok("keyfile", 1); 키값생성 17 msgid = msgget(key, IPC_CREAT 0644); 18 if (msgid == 1) { 19 perror("msgget"); 20 exit(1); 21 } 22 메시지큐생성 11/42 12/42

[ 예제 10-1] 메시지큐생성및메시지전송하기 ex10_1.c 메시지큐 [4] 23 mesg.mtype = 1; 24 strcpy(mesg.mtext, "Message Q Test\n"); 보낼메시지만들기 25 26 if (msgsnd(msgid, (void *)&mesg, 80, IPC_NOWAIT) == 1) { 27 perror("msgsnd"); 28 exit(1); 메시지전송 29 } 30 31 return 0; 32 } # ex10_1.out # ipcs qo IPC status from <running system> as of 2009 년 2 월 18 일수요일오후 2 시 01 분 14 초 T ID KEY MODE OWNER GROUP CBYTES QNUM q 1 0x100719c rw r r root other 80 1 메시지수신 : msgrcv(2) #include <sys/msg.h> ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long int msgtyp, int msgflg); msqid : 메시지큐식별자 msgp : 메시지버퍼주소 msgsz : 메시지버퍼크기 msgtyp : 읽어올메시지유형 msgflg : 블록모드 (0)/ 비블록모드 (IPC_NOWAIT) msgtyp 에지정할값 0 : 메시지큐의다음메시지를읽어온다. 양수 : 메시지큐에서 msgtyp 로지정한유형과같은메시지를읽어온다. 음수 : 메시지의유형이 msgtyp 로지정한값의절대값과같거나작은메시지를읽어온다. 13/42 14/42 [ 예제 10-2] 메시지수신하기 ex10_2.c 메시지큐 [5] 메시지제어 : msgctl(2) 05 struct mymsgbuf { 06 long mtype; #include <sys/msg.h> 07 char mtext[80]; 메시지버퍼정의 int msgctl(int msqid, int cmd, struct msqid_ds *buf); 08 09 msqid : 메시지큐식별자 10 int main(void) { 11 struct mymsgbuf inmsg; cmd : 수행할제어기능 12 key_t key; buf : 제어기능에사용되는메시지큐구조체주소 13 int msgid, len; 14 15 key = ftok("keyfile", 1); 송신측과같은키값생성 cmd에지정할값 16 if ((msgid = msgget(key, 0)) < 0) { IPC_RMID : 메시지큐제거 17 perror("msgget"); IPC_SET : 메시지큐정보중 msg_perm.uid, msg_perm.gid, msg_perm.mode, 18 exit(1); msg_qbytes 값을세번째인자로지정한값으로변경 19 } IPC_STAT : 현재메시지큐의정보를 buf에저장 20 메시지수신 21 len = msgrcv(msgid, &inmsg, 80, 0, 0); 22 printf("received Msg = %s, Len=%d\n", inmsg.mtext, len); 23 # 24ex10_2.out return 0; Received 25 } Msg = Message Q Test, Len=80 # ipcs qo IPC status from <running system> as of 2009년 2월 18일수요일오후 2시 03분 48초 T ID KEY MODE OWNER GROUP CBYTES QNUM q 1 0x100719c rw r r root other 0 0 15/42 16/42

[ 예제 10-3] 메시지큐삭제하기 ex10_3.c [ 예제 10-3] 실행결과 05 int main(void) { 06 key_t key; 07 int msgid; 08 09 key = ftok("keyfile", 1); 키값생성 10 msgid = msgget(key, IPC_CREAT 0644); 11 if (msgid == 1) { 12 perror("msgget"); 13 exit(1); 14 } 15 16 printf("before IPC_RMID\n"); 17 system("ipcs q"); 18 msgctl(msgid, IPC_RMID, (struct msqid_ds *)NULL); 19 printf("after IPC_RMID\n"); 20 system("ipcs q"); 21 22 return 0; 23 } 메시지큐삭제 # ex10_3.out Before IPC_RMID IPC status from <running system> as of 2009 년 2 월 18 일수요일오후 2 시 21 분 47 초 T ID KEY MODE OWNER GROUP q 1 0x100719c rw r r root other After IPC_RMID IPC status from <running system> as of 2009 년 2 월 18 일수요일오후 2 시 21 분 47 초 T ID KEY MODE OWNER GROUP 17/42 18/42 공유메모리 [1] 공유메모리 같은메모리공간을두개이상의프로세스가공유하는것 같은메모리공간을사용하므로이를통해데이터를주고받을수있음 공유메모리생성 : shmget(2) #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); key : IPC_PRIVATE 또는 ftok 로생성한키값 size : 공유할메모리크기 shmflg : 공유메모리의속성을지정하는플래그 IPC_CREAT, IPC_EXCL 공유메모리식별자를리턴 (shmid_ds 구조체 ) 공유메모리 [2] shmid_ds 구조체 struct shmid_ds { struct ipc_perm msg_perm; size_t shm_segsz; struct anon_map *shm_amp; pid_tt_t shm_lpid;; pid_t shm_cpid; shmatt_t shm_nattch; ulong_t shm_cnattch; time_t shm_atime; int32_t shm_pad1; time_t shm_dtime; int32_t shm_pad2; time_t shm_ctime; int32_t shm_pad3; int32_t shm_pad4[4]; shm_perm: IPC 공통구조체 shm_segsz: 공유메모리세그먼트크기 shm_lpid: 마지막으로 shmop 동작을한프로세스 ID shm_cpid : 공유메모리를생성한프로세스 ID shm_nattach: 공유메모리를연결하고있는프로세스수 shm_atime: 마지막으로공유메모리를연결한시각 shm_dtime: 마지막으로공유메모리연결을해제한시각 shm_ctime: 마지막으로공유메모리접근권한을변경한시각 19/42 20/42

[ 예제 10-4] 공유메모리생성하기 ex10_4.c 07 int main(void) { 08 key_t key; 09 int shmid; 10 키생성 11 key = ftok("shmfile", 1); 12 shmid = shmget(key, 1024, IPC_CREAT 0644); 13 if (shmid == 1) { 14 perror("shmget"); 15 exit(1); 16 } 17 18 return 0; 19 } 공유메모리생성. # ex10_4.out # ipcs mo IPC status from <running system> as of 2009 년 2 월 18 일수요일오후 03 시 06 분 01 초 T ID KEY MODE OWNER GROUP NATTCH Shared Memory: m 0 0x100719b rw r r root other 0 공유메모리 [3] 공유메모리연결 : shmat(2) #include <sys/shm.h> void *shmat(int shmid, const void *shmaddr, int shmflg); shmid : 공유메모리식별자 shmaddr : 공유메모리를연결할주소 shmflg : 공유메모리에대한읽기 / 쓰기권한 0( 읽기 / 쓰기가능 ), SHM_RDONLY( 읽기전용 ) 공유메모리연결해제 : shmdt(2) #include <sys/shm.h> int shmdt(char *shmaddr); shmaddr: 연결을해제힐공유메모리주소 21/42 22/42 공유메모리 [4] 공유메모리제어 : shmctl(2) #include <sys/shm.h> int shmctl(int shmid, int cmd, struct shmid_ds *buf); cmd : 수행할제어기능 IPC_RMID : 공유메모리제거 IPC_SET : 공유메모리정보내용중 shm_perm.uid, shm_perm.gid, shm_perm.mode 값을세번째인자로지정한값으로변경 IPC_STAT : 현재공유메모리의정보를 buf 에지정한메모리에저장 SHM_LOCK : 공유메모리를잠근다. SHM_UNLOCK : 공유메모리의잠금을해제한다. [ 예제 10-5] 공유메모리사용하기 부모 / 자식프로세스간공유메모리사용예제 09 int main(void) { 10 int shmid, i; 11 char *shmaddr, *shmaddr2; 12 13 shmid = shmget(ipc_private, 20, IPC_CREAT 0644); 14 if (shmid == 1) { 15 perror("shmget"); 공유메모리생성 16 exit(1); 17 } 18 19 switch (fork()) { 20 case 1: 21 perror("fork"); 22 exit(1); 23 break; ex10_5.c 23/42 24/42

[ 예제 10-5] 공유메모리사용하기 ex10_5.c [ 예제 10-6] (1) listener ( 서버역할 ) ex10_6s.c 24 case 0: 25 shmaddr = (char *)shmat(shmid, (char *)NULL, 0); 26 printf("child Process =====\n"); 27 for (i=0; i<10; i++) 28 shmaddr[i] = 'a' + i; 29 shmdt((char *)shmaddr); 공유메모리에데이터기록후 30 exit(0); 공유메모리연결해제 31 break; 32 default: 33 wait(0); 34 shmaddr2 = (char *)shmat(shmid, (char *)NULL, 0); 35 printf("parent Process =====\n"); 36 for (i=0; i<10; i++) 37 printf("%c ", shmaddr2[i]); 38 printf("\n"); 39 sleep(5); 공유메모리연결해제 40 shmdt((char *)shmaddr2); 41 shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); 42 break; 43 } 44 45 return 0; 46 } 공유메모리삭제 공유메모리연결 공유메모리연결 공유메모리내용출력 # ex10_5.out Child Process ===== Parent Process ===== a b c d e f g h i j 25/42 독립적인프로세스간공유메모리사용예제 10 void handler(int dummy) { 11 ; 12 } 13 14 int main(void) { 15 key_t key; 16 int shmid; 17 void *shmaddr; 18 char buf[1024]; 19 sigset_t mask; 20 21 key = ftok("shmfile", 1); 키생성 22 shmid = shmget(key, 1024, IPC_CREAT 0666); 23 24 sigfillset(&mask); 25 sigdelset(&mask, SIGUSR1); 26 sigset(sigusr1, handler); 27 28 printf("listener wait for Talker\n"); 시그널처리지정 공유메모리생성 26/42 [ 예제 10-6] (1) listener ( 서버역할 ) ex10_6s.c 29 sigsuspend(&mask); 시그널올때까지대기 30 31 printf("listener Start =====\n"); 32 shmaddr = shmat(shmid, NULL, 0); 시그널이오면공유메모리연결 33 strcpy(buf, shmaddr); 34 printf("listener received : %s\n", buf); 메모리내용읽고출력 35 36 strcpy(shmaddr, "Have a nice day\n"); 37 sleep(3); 공유메모리에쓰기 38 shmdt(shmaddr); 39 40 return 0; 41 } [ 예제 10-6] (2) talker( 클라이언트역할 ) ex10_6c.c 11 int main(int argc, char **argv) { 12 key_t key; 13 int shmid; 14 void *shmaddr; 15 char buf[1024]; 16 17 key = ftok("shmfile", 1); 서버와같은키생성 18 shmid = shmget(key, 1024, 0); 공유메모리정보가져오기 19 20 shmaddr = shmat(shmid, NULL, 0); 21 strcpy(shmaddr, "Hello, I'm talker\n"); 공유메모리연결하고데이터기록 22 23 kill(atoi(argv[1]), SIGUSR1); 24 sleep(2); 시그널발송 25 strcpy(buf, shmaddr); 26 27 printf("listener said : %s\n", buf); 28 system("ipcs mo"); 서버가보낸메시지읽어출력 29 shmdt(shmaddr); 30 shmctl(shmid, IPC_RMID, NULL); 공유메모리연결해제및삭제 31 32 return 0; 33 } 27/42 28/42

[ 예제 10-6] 실행결과 # listener & [1] 4946 # Listener wait for Talker Listener Start ===== Listener received : Hello, I'm talker # talker 4946 Listener said : Have a nice day IPC status from <running system> as of 2009 년 2 월 18 일수요일오후 07 시 53 분 12 초 T ID KEY MODE OWNER GROUP NATTCH Shared Memory: m 4 0x100719b rw rw rw root other 2 # ipcs IPC status from <running system> as of 2009 년 2 월 18 일수요일오후 07 시 53 분 57 초 T ID KEY MODE OWNER GROUP Shared Memory: Semaphores: 세마포어 [1] 세마포어 프로세스사이의동기를맞추는기능제공 한번에한프로세스만작업을수행하는부분에접근해잠그거나, 다시잠금을해제하는기능을제공하는정수형변수 세마포어를처음제안한에츠허르데이크스트라가사용한용어에따라잠금함수는 p 로표시하고해제함수는 v 로표시 세마포어기본동작구조 중요처리부분 (critical section) 에들어가기전에 p 함수를실행하여잠금수행 처리를마치면 v 함수를실행하여잠금해제 p(sem); // 잠금중요한처리부분 v(sem); // 잠금해제 29/42 30/42 세마포어 [2] p 함수의기본동작구조 p(sem) { while sem=0 do wait; sem 값을 1 감소 ; } sem 의초기값은 1 sem 이 0 이면다른프로세스가처리부분을수행하고있다는의미이므로 1 이될때까지기다린다. sem 이 0 이아니면 0 으로만들어다른프로세스가들어오지못하게함 v 함수의기본동작구조 v(sem) { sem 값을 1 증가 ; if ( 대기중인프로세스가있으면 ) 대기중인첫번째프로세스를동작시킨 } 31/42 세마포어 [3] 세마포어생성 : semget(2) #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); nsems : 생성할세마포어개수 semflg : 세마포어접근속성 (IPC_CREAT, IPC_EXCL) semid_ds 구조체 struct semid_ds { struct ipc_perm sem_perm; struct sem *sem_base; ushort_t sem_nsems; time_t sem_otime; int32_t sem_pad1; time_t sem_ctime; int32_t sem_pad2; int sem_binary; long sem_pad3[3]; sem_perm: IPC 공통구조체 sem_base: 세마포어집합에서첫번째세마포어의주소 sem_nsems: 세모포어집합에서세마포어개수 sem_otime: 세마포어연산을수행한마지막시간 sem_ctime: 세마포어접근권한을마지막으로변경한시간 sem_binary: 세마포어종류를나타내는플래그 32/42

세마포어 [4] 세마포어 [5] sem 구조체 세마포어정보를저장하는구조체 struct sem { ushort_t semval; pid_t sempid; ushort_t semncnt; ushort_t semzcnt; kcondvar_t semncnt_cv; kcondvar_t semzcnt_cv; semval : 세마포어값 sempid : 세마포어연산을마지막으로수행한프로세스 PID semncnt: 세마포어값이현재값보다증가하기를기다리는프로세스수 semzcnt: 세마포어값이 0 이되기를기다리는프로세스수 33/42 세마포어제어 : semctl(2) #include <sys/sem.h> int semctl(int semid, int semnum, int cmd, ); semnum : 기능을제어할세마포어번호 cmd : 수행할제어명령 : 제어명령에따라필요시사용할세마포어공용체주소 ( 선택사항 ) union semun { int val; struct semid_df * buf; ushort_t *array; } arg; cmd에지정할수있는값 IPC_RMID, IPC_SET, IPC_STAT : 메시지큐, 공유메모리와동일기능 GETVAL : 세마포어의 semval 값을읽어온다. SETVAL : 세마포어의 semval 값을 arg.val로설정한다. GETPID : 세마포어의 sempid 값을읽어온다. GETNCNT, GETZNCNT : 세마포어의 semncnt, semzcnt 값을읽어온다. GETALL : 세마포어집합에있는모든세마포어의 semval 값을 arg.array에저장 SETALL : 세마포어집합에있는모든세마포어의 semval 값을 arg.array의값으로설정 34/42 세마포어 [6] 세마포어 [7] 세마포어연산 : semop(2) #include <sys/sem.h> int semop(int semid, struct sembuf *sops, size_t nsops); sops : sembuf 구조체주소 nsops : sops 가가리키는구조체크기 세마포어연산 sembuf 구조체의 sem_op 항목에지정 세마포어연산을의미 if (sem_op < 0) { /* 세마포어잠금 */ wait until semval >= sem_op ; semval -= sem_op ; } else if (sem_op > 0) /* 세마포어잠금해제 */ semval += sem_op; else wait until semval is 0; struct sembuf { ushort_t short short sem_num; sem_op; sem_flg; 35/42 1. sem_op 가음수 : 세마포어잠금기능수행 semval 값이 sem_op 의절댓값과같거나크면 semval 값에서 sem_op 의절댓값을뺀다. semval 값이 sem_op 값보다작고 sem_flg 에 IPC_NOWAIT 가설정되어있으면 semop 함수는즉시리턴 semval 값이 sem_op 값보다작은데 sem_flg 에 IPC_NOWAIT 가설정되어있지않으면 semop 함수는 semncnt 값을증가시키고다음상황을기다린다. 1 semval 값이 sem_op의절대값보다같거나커진다. 이경우 semncnt 값은감소하고 semval 값에서 sem_op의절대값을뺀다. 2 시스템에서 semid가제거된다. 이경우 errno가 EIDRM으로설정되고 -1을리턴한다. 3 semop 함수를호출한프로세스가시그널을받는다. 이경우 semncnt 값은감소하고시그널처리함수를수행한다. 2. sem_op 가양수면이는세마포어의잠금을해제하고사용중이던공유자원을돌려준다. 이경우 sem_op 값이 semval 값에더해진다. 3. sem_op 값이 0 일경우 semval 값이 0 이면 semop 함수는즉시리턴한다. semval 값이 0 이아니고, sem_flg 에 IPC_NOWAIT 가설정되어있으면 semop 함수는즉시리턴한다. semval 값이 0 이아니고, sem_flg 에 IPC_NOWAIT 가설정되어있지않으면 semop 함수는 semzcnt 값을증가시키고 semval 값이 0 이되길기다린다. 36/42

[ 예제 10-7] (1) 세마포어생성과초기화 ex10_7.c 09 union semun { 10 int val; 11 struct semid_ds *buf; semun 공용체선언 12 unsigned short *array; 13 14 15 int initsem(key_t semkey) { 세마포어생성및초기화함수 16 union semun semunarg; 17 int status = 0, semid; 18 세마포어생성 19 semid = semget(semkey, 1, IPC_CREAT IPC_EXCL 0600); 20 if (semid == 1) { 21 if (errno == EEXIST) 22 semid = semget(semkey, 1, 0); 23 } 24 else { 25 semunarg.val = 1; 세마포어값을 1로초기화 26 status = semctl(semid, 0, SETVAL, semunarg); 27 } 28 29 if (semid == 1 status == 1) { 30 perror("initsem"); 31 return ( 1); 32 } 33 34 return semid; 35 } 37/42 [ 예제 10-7] (2) 세마포어연산 36 37 int semlock(int semid) { 세마포어잠금함수 38 struct sembuf buf; 39 40 buf.sem_num = 0; 41 buf.sem_op = 1; sem_op 값을음수로하여잠금기능수행 42 buf.sem_flg = SEM_UNDO; 43 if (semop(semid, &buf, 1) == 1) { 44 perror("semlock failed"); 45 exit(1); 46 } 47 return 0; 48 } 49 50 int semunlock(int semid) { 세마포어잠금해제함수 51 struct sembuf buf; 52 53 buf.sem_num = 0; 54 buf.sem_op = 1; sem_op 값을양수로하여잠금해제기능수행 55 buf.sem_flg = SEM_UNDO; 56 if (semop(semid, &buf, 1) == 1) { 57 perror("semunlock failed"); 58 exit(1); 59 } 60 return 0; 61 } ex10_7.c 38/42 [ 예제 10-7] (3) 세마포어호출 ex10_7.c [ 예제 10-7] 실행결과 63 void semhandle() { 64 int semid; 65 pid_t pid = getpid(); 66 67 if ((semid = initsem(1)) < 0) 세마포어생성함수호출 68 exit(1); 69 70 semlock(semid); 세마포어잠금함수호출 71 printf("lock : Process %d\n", (int)pid); 72 printf("\n"); 처리부분 73 sleep(1); 74 printf("unlock : Process %d\n", (int)pid); 75 semunlock(semid); 76 77 세마포어잠금해제함수호출 exit(0); 78 } 79 80 int main(void) { 81 int a; 82 for (a = 0; a < 3; a++) 자식프로세스를 3개만든다. 83 if (fork() == 0) semhandle(); 84 85 return 0; 86 } 39/42 세마포어기능을사용하지않을경우 # ex10_7.out Lock : Process 5262 Lock : Process 5263 Lock : Process 5264 Unlock : Process 5263 Unlock : Process 5262 Unlock : Process 5264 세마포어기능을사용할경우 # ex10_7.out Lock : Process 5195 Unlock : Process 5195 Lock : Process 5196 Unlock : Process 5196 Lock : Process 5197 Unlock : Process 5197 5262 프로세스가처리부분을실행하는중에다른프로세스도같이수행된다. 5262 프로세스가처리부분을실행하는중에다른프로세스는실행하지않고차례로실행한다. 40/42

IT CookBook, 유닉스시스템프로그래밍