[ CODE ] IPC

38A·2023년 4월 22일
1

Operating System

목록 보기
11/14
post-thumbnail

[System V] Shared-Memory

✔️ shmget()

: Create shared memory

int shmget(key_t key, int size, int shmflg);
return seg_id, if fail return -1

➡️ 주소는 절대적인 주소가 아닌, process안에서만 통용된다. physical주소로 mapping

Parameter

key : Key of shared memory segment

  • IPC_PRIVATE : key를 IPC_PRIVATE로 설정하면, key값은 중복되지 않는 임의의 값으로 자동으로 생성

size : memory block size

  • 할당할 메모리의 byte단위 크기, 주로 Buffer size

shmflg : flags

  • S_IRUSR : User readable
  • S_IWUSR : User writable
  • IPC_CREAT : key에 해당하는 메모리가 없으면 공유메모리를 생성 ( 0666 )
  • IPC_EXCL : key 값에 해당하는 공유 메모리가 있다면 실패 반환, 접근 막음

✔️ shmat()

: Attach shared memory to address space of a process
: 공유 메모리를 마치 프로세스의 몸 안으로 첨부

void* shmat(int shmid, char *shmaddr, int shmflg);
return memory address, if fail return -1

➡️ void* : 특정 type에 국한 x

Parameter

shmid : shmget() 리턴으로 얻은 shmid(seg_id)
shmaddr : mapping 위치 ( NULL : kernel이 알아서 지정 )
shmflg : attach flags

✔️ shmdt()

: Detach shared memory from address space of process
: 프로세스에 첨부된 공유 메모리를 프로세스에서 분리

void shmdt(char *shmaddr);
return 0, if fail return -1

✔️ shmctl()

: Controls and deallocate a shared memory block
: 공유 메모리 정보 확인 / 변경 / 제거

shmctl(shmid, IPC_RMID, NULL);
IPC_RMID : RM(remove)ID

➡️ 명령 직후 삭제 x, 쓰는 process가 없을 때 (shm_attach == 0) 삭제 예약

[ POSIX ] Shared Memory

gcc main.c -lrt

✔️ shm_open()

: Process creates or open shared memory segment

int shm_open(const char *name, int oflag, mode_t mode);
return fd, if fail return -1

Parameter

name : 공유메모리 이름

oflag : open flag

  • O_RDONLY : Read only
  • O_RDWR : Read and Write mode
  • O_CREAT : Create if it does not yet exist
  • O_EXCL : O_CREAT 지정했을 때, 공유메모리가 이미 존재하면 오류 반환
  • O_TRUNC : 공유메모리가 이미 있으면, truncate it to zero bytes.

shmflg : attach flags ( permission )

shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);

int shm_unlink(const char *name);
return 0, if fail return -1

공유 메모리는 커널이 종료되기 전까지는 제거되지 않음

✔️ ftruncate()

: Set the size of the object

int ftruncate(int fd, size_t length);
return 0, if fail return -1

Parameter

fd : 쓰기 mode로 설정된 fd (O_WRONLY, O_RDWR)
length : 조정할 파일 size

ftruncate(shm_fd, 4096);

✔️ mmap()

void mmap(void start, size_t length, int prot, int flags, int fd, off_t offset);
return 대응된 영역의 포인터, if fail return -1

➡️ fd로 지정된 파일(혹은 다른 객체)에서 offset을 시작으로 length바이트 만큼을 start주소로 대응시키도록 한다.

Parameter

prot : protection flag

  • PROT_EXEC : 페이지 실행 가능
  • PROT_READ : 페이지 읽기 가능
  • PROT_WRITE : 페이지 쓰기 가능
  • PROT_NONE : 페이지 접근 불가

flag : 대응된 객체의 타입, 대응 옵션, 대응된 페이지 복사본에 대한 수정이 그 프로세스에만 보일 것인지, 다른 참조하는 프로세스와 공유할 것인지를 설정

  • MAP_FIXED : 지정된 주소 이외의 주소를 선택하지 않음
  • MAP_SHARED : 대응된 객체를 다른 모드 프로세스와 공유
  • MAP_PRIVATE : 개별적인 대응을 만듬
shared_memory = mmap(0, 4096, PROT_WRTIE, MAP_SHARED, shm_fd, 0);

✔️ munmap()

int munmap(void *start, size_t length);
return 0, if fail return -1

Parameter

start : 맵핑이 시작된 첫 번째 주소를 나타낸다.
→ mmap 함수의 return 값이다.

process 종료 시 자동으로 unmap

munmap(shared_memory, 4096);

[ POSIX ] Message Passing

typedef struct {
   	long  type;
    int index;
   	char  content[MAX_LEN];
} Message;

✔️ msgget()

: create a message queue

int msgget( key_t key, int msgflg );
return 메시지 큐 식별자, if fail return -1

Parameter

key : 시스템에서 다른 큐와 구별되는 번호
msgflg : 옵션

msqid_p2c = msgget((key_t)p2c_key, IPC_CREAT | 0666);
msqid_c2p = msgget((key_t)c2p_key, IPC_CREAT | 0666);

✔️ msgsnd()

: send a message to a message queue

int msgsnd( int msqid, const void *msgp, size_t msgsz, int msgflg );
return 0, if fail return -1

Parameter

msqid : 메시지 큐 식별자
msgp : 전송할 자료

msgsz : 전송할 자료의 크기

typedef struct {
 	long  type;
  	int index;
 	char  content[MAX_LEN];
} Message;
  • 전송 데이터는 long 값을 첫번째에 가지고 있어, 원하는 데이터만 걸러낼 수 있다. 따라서, 데이터의 크기에 long 값이 반드시 들어가기 때문에 type을 나타내는 long크기는 제거한다.
    ➡️ sizeof(msg) - sizeof(long)

msgflg : 동작 옵션

  • 전송 실패시 0은 큐에 공간이 생길 때까지 wait
  • IPC_NOWAIT은 바로 -1을 리턴
Message out_msg;
size_t msg_size = sizeof(Message) - sizeof(long);
out_msg.type = MSG_P2C;	
out_msg.index = 0;

int res_snd = msgsnd(p2c, &out_msg, msg_size, 0);
if(res_snd == -1) 
	fprintf(stderr, "Failed to send the expression to the child\n");

✔️ msgrcv()

: receive a message from a message queue

ssize_t msgrcv( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg );
return data size, if fail return -1

Parameter

msqp : 수신한 데이터

msgtyp : 메시지 큐에 있는 데이터 중 어떤 데이터를 읽어 들일지에 대한 옵션

  • 0이면 큐의 첫번째 자료를 read
  • 양수일 경우, 양수로 지정한 값과 동일한 데이터 타입의 자료 중 첫번째 Read
  • 음수일 경우, 음수 값을 절대 값으로 바꾼 후, 이 절대값과 같거나 가장 작은 데이터 타입의 데이터를 Read

msgflg : 동작 옵션

  • 전송 실패시 0은 큐에 공간이 생길 때까지 wait
  • IPC_NOWAIT은 바로 -1을 리턴
Message in_msg;
size_t msg_size = sizeof(Message) - sizeof(long);
    
int res_rcv = msgrcv(p2c, &in_msg, msg_size, 0, 0);
if(res_rcv == -1) 
	fprintf(stderr, "Failed to receive the result from the child\n");

✔️ msgctl()

메시지큐 상태 정보 · 변경 · 삭제

int msgctl ( int msqid, int cmd, struct msqid_ds *buf )
return 0, if fail return -1

Parameter

cmd

  • IPC_RMID : 메시지 큐를 삭제 ➡️ buffer가 필요없으므로 0으로 지정
  • IPC_STAT : 현재 상태를 buf에 저장
  • IPC_SET : 현재 상태를 buf 값으로 변경

buf : 메시지 큐 정보를 받을 버퍼

msgctl(msqid_p2c, IPC_RMID, 0);
msgctl(msqid_c2p, IPC_RMID, 0);
profile
HGU - 개인 공부 기록용 블로그

0개의 댓글