[Linux, OS] POSIX Semaphore & Shared Memory | System V Message Queue & Semaphore & Shared Memory

pos++·2024년 1월 4일
0

Linux

목록 보기
13/16
post-thumbnail

2023.11.16 TIL

Code, Image source: The Linux Programming Interface, Michael Kerrisk

Semaphore

  • Named Semaphores

    • File system에 file이 생김 → file descriptor가 할당됨 → 서로 다른 두 Process가 바라볼 수 있음
    • Process간 동기화
    • 조금 더 무거움
  • Unnamed Semaphores

    • Memory 할당 Global variable로 선언 (mutex처럼)
      • 같은 memory를 사용하는 fork → exec은 부모의 fd가 사라지기 때문에 named semaphore가 필요함
    • Thread간 동기화
    • 조금 더 가벼움

Named Semaphore

psem_create

#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag, ... /* mode_t mode, unsigned int value*/ );
  • Returns pointer to semaphore on success, or SEM_FAILED on error
  • tlpi-dist/psem/psem_create.c

Closing a Semaphore

#include <semaphore.h>

int sem_close(sem_t *sem);
#include <semaphore.h>

int sem_unlink(const char *name);
  • File system에 경로를 지워 완전히 clear

Semaphore Action

  • sem_post()

    #include <semaphore.h>
    
    int sem_wait(sem_t *sem);
    • Semaphore 값을 1씩 증가
    • tlpi-dist/psem/psem_post.c
  • sem_wait()

    #include <semaphore.h>
    
    int sem_post(sem_t *sem);
    • Semaphore 값을 1씩 감소
    • 만약 감소 값이 0보다 작다면 대기
    • tlpi-dist/psem/psem_wait.c
$ ./psem_create -c /demo 600 0
$ ./psem_wait /demo &  # 0이니까 기다림
[1] 31208
$ ./psem_getvalue /demo
0
$ ./psem_post /demo
$ 31208 sem_wait() succedded  # 1로 변해서 wakeup, 돌아감

Press Enter
[1]- Done        ./psem_wait /demo
$ ./psem_post /demo
$ ./psem_getvalue /demo
1
$ ./psem_unlink /demo

Unnamed Semaphore

Initialize

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);
  • pshared : 공유변수, 0이면 thread간 공유, 1이면 process fork해서 공유

  • tlpi-dist/psem/thread_incr_psem.c


Destroy

#include <semaphore.h>

int sem_destroy(sem_t *sem);

Shared Memory

Process간 Memory 공유

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>

int shm_open(const char *name, int oflag, mode_t mode);
  • oflag
    • O_CREAT : Create object if it doesn’t already exist
    • O_EXCL : With O_CREAT, create object exclusively
    • O_RDONLY : Open for read-only access
    • O_RDWR : Open for read-write access
    • O_TRUNC : Truncate object to zero length

Shared Memory 생성

  • tlpi-dist/pshm/pshm_create.c

Shared Memory 사용

  • tlpi-dist/pshm/pshm_write.c
  • tlpi-dist/pshm/pshm_read.c
$ ./pshm_create -c /demo_shm 0
$ ls -l /dev/shm
total 4
-rw-------    1 mtk    users   0 Jun 21 13:33 demo_shm

$ ./pshm_write /demo_shm 'hello'
$ ls -l /dev/shm
total 4
-rw-------    1 mtk    users   5 Jun 21 13:33 demo_shm  # size 5byte 증가

$ ./pshm_read /demo_shm
hello

System V IPC

  • 전통적인 IPC 방법
  • POSIX IPC같은 fdr가 아닌 key 기반 → Key는 Kernel이 관리
  • 주로 POSIX IPC를 쓰지만, System V IPC중 Shared memory는 쓸만함

IPC Keys

  • IPC 통신을 위한 system의 유일한 key
  • 생성 방법
    • IPC 객체를 만들 때 IPC_PROVATE를 이용
    • ftok() 함수를 이용

Cleanup of IPC objects within a server

  • tlpi-dist/svipc/svmsg_demo_server.c
  • #define KEY_FILE "/some-path/some-file"
  • key = ftok(KEY_FILE, 1);

ipcs, iprm commands

  • $ ipcs → System의 전반적인 key값 조회(key, shmid, owner, perms, bytes, ...)
    • Shared Memory Segments, Semaphore Arrays
  • $ ipcrm -X key → key로 지우기
  • $ ipcrm -x id → id로 지우기

System V Semaphore

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

int semget(key_t key, int nsems, int semflg);

Semaphore Control Operations

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

int semctl(int semid, int semnum, int cmd, ... /* union semun arg */ );
#include <sys/types.h>
#include <sys/sem.h>

int semop(int semid, struct sembuf *sops, unsigned int nsops);
$ ./svsem_demo 0  # Semaphore를 0으로 생성
Semaphore ID = 98307

$ ./svsem_demo 98307 -2 &  # 0보다 작으니까 대기
23338: about to semop at 10:19:42
[1] 23338

$ ./svsem_demo 98307 +3  # wakeup
23339: about to semop at 10:19:55
23339: semop completed at 10:19:55
23338: semop completed at 10:19:55
[1]+  Done              ./semop_demo98307 -2

svsem_demo.c

  • tlpi-dist/svsem_demo.c
  • argument가 2개이면 create, init-value를 argument 값으로 설정

Binary Semaphore

  • tlpi-dist/svsem/binary_sems.h
  • tlpi-dist/svsem/binary_sems.c

Shared Memory

Shared Memory Segment 할당

#include <sys/types.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

Attach

#include <sys/types.h>
#include <sys/shm.h>

int *shmat(int shmid, const void *shmaddr, int shmflg);
  • 사용하는 process가 사용하겠다고 attach

Detach

#include <sys/types.h>
#include <sys/shm.h>

int semop(const void *shmaddr);

Remove

shmctl(int id, IPC_RMID, int flag)
$ wc -c /etc/services             # Display size of test file
764360 /etc/services
$ ./svshm_xfr_writer < /etc/services &
[1] 9403
$ ./svshm_xfr_reader > out.txt
Received 764360 bytes (747 xfrs)  # message from reader
Sent 764360 bytes (747 xfrs)      # message from writer
[1]+  Done           ./svshm_xfr_writer < /etc/services 
$ diff /etc/services out.txt
  • tlpi-dist/svshm_xfr.h → key는 그냥 여기서 한거처럼 하드코딩 (0x1234, 0x5678)

Writing Data to Shared Memory

  • tlpi-dist/svshm/svshm_xfr_writer.c
  • Key로 id 가져오기
  • Binary semaphore 생성
  • Attach Shared memory

Reading Data from Shared Memory

  • tlpi-dist/svshm/svshm_xfr_reader.c

Shared Memory 들여다보기

  • Shared Memory의 위치
    • Stack과 Heap의 사이 공간
  • $ cat /proc/[PID]/maps
    • Process의 Address Space 확인 가능
profile
밀린 TIL 업로드 조금씩 정리중...

0개의 댓글