Process synchronization

  • 다중 프로그래밍 시스템
    • 여러 개의 프로세스들이 존재
    • 프로세스들은 서로 독립적으로 동작
    • 공유 자원 또는 데이터가 있을 때, 문제 발생 가능
  • 동기화
    • 프로세스들이 서로 동작을 맞추는 것
    • 프로세스들이 서로 정보를 공유하는 것

Mutaul exclusion primitives

  • enterCS()
    • Critical section 진입 전 검사
    • 다른 프로세스가 critical section안에 있는지 검사
  • exitCS()
    • critical section을 벗어날 때의 후처리 과정
    • critical section을 벗어남을 시스템이 알림

Semaphore

  • 1965년 Dijkstra가 제안
  • Busy waiting 문제 해결
  • 음이 아닌 정수형 변수(S)
    • 초기화 연산, P(), V()로만 접근 가능
      • P: Probern(검사)
      • V: Verhogen(증가)
  • 임의의 S 변수 하나에 ready queue 하나가 할당됨
  • Binary semaphore
    • S가 0과 1 두 종류의 값만 갖는 경우
    • 상호배제나 프로세스 동기화의 목적으로 사용
  • Counting semaphore
    • S가 0이상의 정수 값을 가질 수 있는 경우
    • Producer-Consumer 문제 등을 해결하기 위해 사용

creating a semaphore array

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int nsems, int semflg);
  • key : IPC key
    • IPC_PRIVATE
  • nsems : 생성할 semaphore 변수 수
    • 하나의 identifier에 여러 개의 변수 생성 가능
  • semflg : 생성 방법 및 접근 권한
    • IPC_CREAT, IPC_EXCL, ...
  • return : 생성된 semaphore 객체의 identifier

operating on a semaphore

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semop(int semid, struct sembuf* sops, size_t nsops);
  • semid : semaphore ID
  • sops : sembuf 구조체 배열
    • sembuf : 수행할 명령을 담은 구조체
    • 순서대로 실행됨
  • nsops : sops가 가리키는 구조체의 수
  • return
    • 0 : success
    • -1 : error

controlling a semaphore

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semctl(int semid, int semnum, int cmd, ...);
  • semid : semaphore array ID
  • semnum : 제어할 semaphore의 번호
  • cmd : 수행할 제어기능
    • IPC_STAT, IPC_RMID
    • GETVAL, SETVAL, GETPID, GETNCNT, GETZCNT
  • ... : cmd에 따라 용도가 지정됨
  • return
    • 0 : success
    • -1 : fail

Example

#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

union semun {
        int val;
        struct semid_ds* buf;
        unsigned short* array;
};

int initsem(key_t semkey) {
        union semun semunarg;
        int status = 0, semid;

        semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0600);
        if (semid == -1) {
                if (errno == EEXIST)
                        semid = semget(semkey, 1, 0);
        }
        else {
                semunarg.val = 1;
                status = semctl(semid, 0, SETVAL, semunarg);
        }

        if (semid == -1 || status == -1) { perror("initsem"); return (-1); }

        return semid;
}

int semlock(int semid) {
        struct sembuf buf;

        buf.sem_num = 0;
        buf.sem_op = -1; // P
        buf.sem_flg = SEM_UNDO;
        if (semop(semid, &buf, 1) == -1) {
                perror("semlock failed");
                exit(1);
        }
        return 0;
}

int semunlock(int semid) {
        struct sembuf buf;

        buf.sem_num = 0;
        buf.sem_op = 1; // V
        buf.sem_flg = SEM_UNDO;
        if (semop(semid, &buf, 1) == -1) {
                perror("semunlock failed");
                exit(1);
        }
        return 0;
}

void semhandle() {
        int semid;
        pid_t pid = getpid();

        if ((semid = initsem(1)) < 0) exit(1);

        semlock(semid);
        printf("Lock : Process %d\n", (int)pid);         // critical
        printf("** Lock Mode : Critical Section\n");     // section
        sleep(1);                                        // critical
        printf("Unlock : Process %d\n", (int)pid);       // section
        semunlock(semid);
        exit(0);
}

int main(void) {
        int a;
        for (a = 0; a < 3; a++)
                if (fork() == 0) semhandle();

        return 0;
}

'💻 Computer Science > System' 카테고리의 다른 글

[System] Socket  (0) 2024.02.02
[System] Shared Memory  (1) 2024.01.26
[System] Named Pipe  (1) 2024.01.26
[System] 메모리 맵핑  (1) 2024.01.26
[System] 시그널  (1) 2024.01.25