1 / 32

Linux System Programming

Linux System Programming. Lecture #10 – 세마포어 (Semaphore). 세마포어 (Semaphore) (1). 세마포어 정의 : 실행단위 ( 프로세스 또는 쓰레드 ) 간의 동기화 도구 2 개의 원자적 연산 P 와 V 가 정의되어 있는 , 정수값을 가지는 객체 s : 세마포어 P(s) : if ( s > 0 ) then s-- else 현재 프로세스는 대기한다 ; V(s) :

july
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 #10 –세마포어(Semaphore)

  2. 세마포어(Semaphore) (1) • 세마포어 정의 : • 실행단위(프로세스 또는 쓰레드) 간의 동기화 도구 • 2개의 원자적 연산 P와 V가 정의되어 있는,정수값을 가지는 객체 • s : 세마포어 • P(s) : if ( s > 0 ) then s-- else현재 프로세스는 대기한다; • V(s) : if ( 1개 이상의 프로세스가 대기중 ) then 1개 프로세스만 진행한다else s++; • 일상 생활에서의 ‘신호등’과 같은 동작을 수행 • 철도 교통을 통제하기 위한 깃발신호로부터 유래 Linux System Programming

  3. 세마포어(Semaphore) (2) • 세마포어 정의 : • 세마포어 연산 P & V 는 원자적 연산(atomic operation) • 하나의 프로세스가 P 또는 V 연산을 실행하는 도중에는 중지하지 않는다 • 어떤 프로세스가 P 또는 V 연산을 이용하여 세마포어에 접근하는 동안에는 다른 프로세스가 세마포어 값을 변경할 수 없다 • 세마포어의 활용 • 상호 배제(mutual exclusion) 문제 –두 개 이상의 프로세스가 하나의 공유 자원을 접근할 때에 한 순간에 하나의 프로세스만 공유 자원을 접근할 수 있도록 보장함 • 실행 동기화 –두 개 이상의 프로세스간에 실행 순서에 맞추어 실행됨을 보장함 Linux System Programming

  4. 세마포어(Semaphore) (3) • 세마포어 종류 : • 이진 세마포어(Binary Semaphore) • 0 또는 1의 정수 값만 가지는 세마포어 • P(s) 연산은 세마포어 s가 1일 때에 0으로 변경 • V(s) 연산은 세마포어 s가 0일 때에 1로 변경 • 하나의 자원에 대한 공유 및 동기화를 지원 • 계수형 세마포어(Counting Semaphore) • 범위에 제한이 없는 정수 값을 가지는 세마포어 • 일반적으로 언급하는 세마포어 • 다수의 공유 자원에 대해 여러 프로세스가 접근할 때에 상호 배제 및 동기화를 지원 Linux System Programming

  5. 세마포어(Semaphore) (4) • 세마포어 이용 : • 공유 자원에 대한 상호 배제(Mutual Exclusion) • 여러 개의 프로세스가 하나의 자원을 공유하는 경우, 동시에 여러 프로세스가 자원을 접근하면 예상하지 못하는 문제가 발생함 • 예: 동시에 여러 프로그램이 프린터에 출력을 시도하는 경우 • 해결책 –상호 배제 • 한 순간에 하나의 프로세스만 공유 자원을 접근함을 보장함 • 임계 영역(Critical Section) : 전체 프로그램 중에서 공유자원을 접근하는 프로그램 영역 • 한 순간에 임계 영역을 실행하는 프로세스는 하나만 존재하도록 보장함 • 세마포어를 이용하여 상호 배제를 구현함 • 공유자원의 갯수에 따라 이진 세마포어 또는 계수형 세마포어를 사용 • 공유 자원에 대한 잠금과 풀기(lock & unlock) 기능을 지원 Linux System Programming

  6. 프로세스 P1 프로세스 P2 세마포어 s (초기값: 1) P(s) V(s) P(s) V(s) Critical Section Critical Section 공유 자원 세마포어(Semaphore) (5) • 세마포어 이용 : • 공유 자원에 대한 상호 배제(Mutual Exclusion) Linux System Programming

  7. 세마포어(Semaphore) (6) • 세마포어 이용 : • 프로세스간의 실행 동기화(Synchronization) • 하나의 프로그램이 여러 개의 프로세스로 이루어지는 경우, 프로세스간의 종속성에 의해 실행 순서가 정해지며, 반드시 실행 순서에 의해 동작하여함 • 예: 하나의 프로세스가 다른 프로세스가 제공하는 데이터를 받아 동작하는 경우 • 해결책 –프로세스 실행 동기화 • 프로세서 P1가 T1 문장을 실행한 후에 프로세스 P2가 T2 문장을 실행하여야 하는 경우 • 프로세스 P2는 T2 문자을 실행하기 전에 프로세스 P1이 T1 문장을 실행하여는지를 검사 • 프로세스 P1이 T1 문장을 실행하였으면 바로 T2 문장을 실행 • 프로세스 P1이 T2 문장을 실행하지 않았으면 실행할 때까지 대기 • 세마포어를 이용하여 동기화를 지원함 • 대개의 경우 이진 세마포어를 사용 Linux System Programming

  8. 프로세스 P2 프로세스 P1 세마포어 s (초기값: 0) V(s) P(s) T1: ----- T2: ----- 세마포어(Semaphore) (7) • 세마포어 이용 : • 프로세스간의 실행 동기화(Synchronization) Linux System Programming

  9. 세마포어(Semaphore) (8) • 세마포어의 생성: semget 시스템 호출 Linux System Programming

  10. 세마포어(Semaphore) (9) • 세마포어의 생성: semget 시스템 호출 • 세마포어 구조체: Linux System Programming

  11. 세마포어(Semaphore) (10) • 세마포어의 생성: semget 시스템 호출 • Semget 시스템 호출의 동작 세마포어 구조체 초기화: Linux System Programming

  12. 세마포어(Semaphore) (11) • 세마포어의 제어: semctl 시스템 호출 • 세마포어 제어 연산 • 세마포어의 집합 안에 개별적인 세마포어나 모든 세마포어에 대해 세마포어 값을 읽어오거나 새로운 값을 설정 • 세마포어 집합의 상태 정보을 읽어오거나 변경 • 세마포어에서 대기중인 프로세스의 수를 결정 • 마지막으로 세마포어를 연산한 프로세스를 결정 • 세마포어를 제거 • semctl 시스템 호출을 통해 상기의 세마포어 제어 연산을 실행 Linux System Programming

  13. 세마포어(Semaphore) (12) • 세마포어의 제어: semctl 시스템 호출 Linux System Programming

  14. 세마포어(Semaphore) (13) • 세마포어의 제어: semctl 시스템 호출 • semctl 시스템 호출의 명령어 및 반환값 Linux System Programming

  15. 세마포어(Semaphore) (14) • 세마포어의 제어: semctl 시스템 호출 • 세마포어 생성 • 세마포어 집합에서 하나의 세마포어를 초기화 • 세마포어 집합에서 하나의 세마포어 값 읽기 #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #define ANY 0 int semid, rtn; struct semid_ds semds; ushort us[5], init_us[5] = {0, 6, 7, 1, 4}; … semid = semget(key, 5, IPC_CREAT|0666); semctl(semid, 2, SETVAL, 7); // GETCNT, GETZCNT, GETPID도 같은 형태로 사용 semctl(semid, 2, GETVAL, ANY); Linux System Programming

  16. 세마포어(Semaphore) (15) • 세마포어의 제어: semctl 시스템 호출 • 세마포어 집합 내의 모든 세마포어의 값을 초기화 • 세마포어 집합 내의 모든 세마포어의 값 읽기 • 세마포어의 소유자 변경 • 세마포어 집합 제거 semctl(semid, ANY, SETALL, init_us); semctl(semid, ANY, GETALL, us); // 접근 허가 모드 변경에도 같은 형태로 사용 semctl(semid, ANY, IPC_STAT, &semds); semds.sem_perm.uid = 51; semctl(semid, ANY, IPC_SET, &ds); semctl(semid, ANY, IPC_RMID, ANY); Linux System Programming

  17. 세마포어(Semaphore) (16) • 세마포어의 제어: semop 시스템 호출 • 세마포어의 값을 증가시키거나 감소시키는 연산을 수행 Linux System Programming

  18. 세마포어(Semaphore) (17) • 세마포어의 제어: semop 시스템 호출 Linux System Programming

  19. 세마포어(Semaphore) (18) • 세마포어의 제어: semop 시스템 호출 Linux System Programming

  20. 예제 프로그램 (1) • 예제 10-1 • 세마포어를 이용하여 공유 자원에 대한 접근을 제어하는 프로그램 • 공유 자원은 표준 출력 // file name : ex10-1.c // #include <sys/ipc.h> #include <sys/sem.h> #include <stdio.h> #define DUMMY 0 #define COUNT 4 int main(int argc, char *argv[]) { key_t ipckey; /* modified */ int semid, semget(),semctl(),semop(); int pid,getpid(); int creator,i; static struct sembuf lock = {0,-1,SEM_UNDO}; static struct sembuf unlock = {0, 1,SEM_UNDO}; setbuf(stdout,(char *) NULL); Linux System Programming

  21. 예제 프로그램 (2) ipckey = ftok(argv[0],'s'); if((semid = semget(ipckey,1,IPC_CREAT | IPC_EXCL | 0666)) != -1) { creator = 1; } else { if((semid = semget(ipckey,1,0)) == -1) { perror(argv[0]); exit(1); } creator = 0; } if(creator) { if(semctl(semid,0,SETVAL,1) == -1) { perror(argv[0]); exit(2); } } pid = getpid(); for(i=0;i<COUNT;i++){ if(semop(semid,&lock,1) == -1) { perror(argv[0]); exit(3); } printf("\t[%d]locking\t",pid); sleep(1); printf("[%d] unlocking\n",pid); if(semop(semid,&unlock,1) == -1) { perror(argv[0]); exit(4); } } Linux System Programming

  22. 예제 프로그램 (3) if(creator) { sleep(5); if(semctl(semid,DUMMY,IPC_RMID,DUMMY) == -1) { perror(argv[0]); exit(5); } } } Linux System Programming

  23. 예제 프로그램 (4) • 예제 10-2 • 다음 그림과 세 개의 세마포어를 갖는 세마포어 집합을 이용하여 프린터 자원을 관리하는 프로그램 • 첫번째 세마포어는 두 개의 프린터 모두를 관리하는 계수형 세마포어 • 두번째 및 세번째 세마포어는 각각 프린터1과 프린터2를 관리하는 세마포어 • 프린터는 단말기 장치를 PRINTER1으로, 정규 파일을 PRINTER2로 환경 변수를 정의하여 시뮬레이션한다 Linux System Programming

  24. 예제 프로그램 (5) #include <fcntl.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <stdio.h> #include "ex10-2.h" #define DUMMY 0 #define NUMPR 2 #define ACQUIRE -1 #define RELEASE 1 int main(int argc,char *argv[]) { char *getenv(), *printer[NUMPR], buf[BUFSIZ]; key_t ipckey; /* modified */ int semid, semget(), semctl(), semop(); ushort initial[NUMPR +1]; int i, prntnum, creator, getpid(); int n, fdin, fdout; struct sembuf operation[2]; char errmsg[30]; if((printer[1] = getenv("PRINTER1")) == (char *) NULL || (printer[2] = getenv("PRINTER2")) == (char *) NULL) { printf("missing printer assignment\n"); exit(1); } Linux System Programming

  25. 예제 프로그램 (6) if(strncmp(argv[0],"line",4) ==0) prntnum = 1; else if(strncmp(argv[0],"lase",4) ==0) prntnum =2; else prntnum = getpid() % NUMPR +1; ipckey = ftok(argv[0], 's'); if((semid = semget(ipckey,NUMPR +1,IPC_CREAT| IPC_EXCL| 0666)) != -1) { creator = 1; } else { if((semid = semget(ipckey, NUMPR +1, 0666)) == -1) { sprintf(errmsg, "%s - semget", argv[0]); perror(errmsg); exit(2); } } if(creator) { /* initialize semaphore set */ initial[0] = NUMPR; for(i=1; i<= NUMPR; i++) initial[i] = 1; if(semctl(semid, DUMMY, SETALL, initial) == -1) { sprintf(errmsg,"%s -SETALL", argv[0]); perror(errmsg); exit(3); } } operation[1].sem_num = prntnum; operation[1].sem_op = ACQUIRE; operation[1].sem_flg = SEM_UNDO; operation[0].sem_num = 0; operation[0].sem_op = ACQUIRE; operation[0].sem_flg = SEM_UNDO; Linux System Programming

  26. 예제 프로그램 (7) if(semop(semid, operation, 2) == -1) { sprintf(errmsg,"%s - ACQUIRE", argv[0]); perror(errmsg); exit(4); } if((fdin = open(argv[1], O_RDONLY)) == -1) { sprintf(errmsg,"%s - %s", argv[0], argv[1]); perror(errmsg); exit(5); } if((fdout = open(printer[prntnum], O_CREAT| O_WRONLY)) == -1) { sprintf(errmsg,"%s - %s", argv[0], printer[prntnum]); perror(errmsg); exit(6); } while((n= read(fdin, buf, BUFSIZ)) > 0) write(fdout, buf, n); operation[1].sem_op = RELEASE; operation[0].sem_op = RELEASE; if(semop(semid, operation, 2) == -1) { sprintf(errmsg,"%s - RELEASE", argv[0]); perror(errmsg); exit(7); } } Linux System Programming

  27. 예제 프로그램 (8) • 예제 10-3 • 다음 그림과 같은 생산 라인을 시뮬레이션하는 프로그램 • 각 공정은 다중 프로세스를 생성하고 이들의 생산 순서와 소비 시간을 세마포어와 프로세스 수면(sleep)을 이용하여 시뮬레이션한다 Linux System Programming

  28. 예제 프로그램 (9) // // header file name : ex10-3.h // #define NWIDGETS 5 #define PARTA 0 #define PARTB 1 #define PARTC 2 #define SUB1 3 #define HOLDER 0 Linux System Programming

  29. 예제 프로그램 (10) // // source file name : ex10-3a.c // #include <signal.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include "ex10-3.h" int semprodn; void endsim(); int main(int argc, char *argv[]) { int widget; int pgrp; char asc_prod_key[20]; static struct sembuf partc_sub1[2] = { { PARTC, -1, SEM_UNDO}, { SUB1, -1, SEM_UNDO} }; if((semprodn=semget(IPC_PRIVATE,4,IPC_CREAT | 0640)) == -1) { printf("Can't get production line semaphore set\n"); exit(1); } Linux System Programming

  30. 예제 프로그램 (11) signal(SIGINT, endsim); sprintf(asc_prod_key,"%d", semprodn); if( fork() == 0) execl("ex10-3b","a", asc_prod_key, (char *)0); if( fork() == 0) execl("ex10-3b","b", asc_prod_key, (char *)0); if( fork() == 0) execl("ex10-3b","c", asc_prod_key, (char *)0); if( fork() == 0) execl("ex10-3c","ex10-3c", asc_prod_key, (char *)0); for(widget=1; widget < NWIDGETS; widget++) { semop(semprodn, partc_sub1, 2); printf("%s: ready to make widget #%d\n", argv[0], widget); } endsim(); } void endsim() { semctl(semprodn, 0,IPC_RMID, 0); signal(SIGTERM, SIG_IGN); kill(0, SIGTERM); exit(); } Linux System Programming

  31. 예제 프로그램 (12) // // source file name : ex10-3b.c // #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include "ex10-3.h" int main(int argc, char *argv[]) { int semprodn, index; int unit = 0; static struct sembuf parti = { HOLDER, 1, SEM_UNDO }; static int prodtimeabc[3] = {2,3,4}; semprodn = atoi( argv[1] ); index = argv[0][0]- 'a'; /* argv[0] == [abc] */ parti.sem_num = index; while(1) { semop(semprodn, &parti, 1); printf("%s: producing unit #%d\n", argv[0], ++unit); sleep(prodtimeabc[index]); } } Linux System Programming

  32. 예제 프로그램 (13) // // source file name : ex10-3c.c // #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include "ex10-3.h" int main(int argc, char *argv[]) { int semprodn; int unit = 0; static struct sembuf part_ab[2] = { {PARTA, -1, SEM_UNDO }, {PARTB, -1, SEM_UNDO } }; static struct sembuf sub1 = { SUB1, 1, SEM_UNDO }; semprodn = atoi( argv[1] ); while(1) { semop(semprodn, part_ab, 2); semop(semprodn, &sub1, 1); printf("%s: producing sub-assembly #%d\n", argv[0], ++unit); } } Linux System Programming

More Related