프로세스는 각자 독립된 메모리 공간을 가지고 있어 서로 간의 데이터를 공유할 방법이 없다. 그렇기에 나온 방식이 IPC로, 프로세스 간 통신을 하는 방법이다.
프로세스 커널이 제공한 IPC 설비를 이용해 프로세스 간 통신을 할 수 있게 되며, IPC 통신 방법에는 여러 가지가 있다.
(공유 메모리 목록 확인) ipcs- m
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
매개변수1 key_t key
시스템에서 공유 메모리를 식별하기 위한 번호
매개변수2 size_t size
공유 메모리의 크기
매개변수3 int shmflg
추가 가능한 옵션
- IPC_CREAT
퍼미션 0666을 설정한다. 첫번째 인수 key에 해당하는 메모리가 없으면 공유 메모리를 생성한다.
- IPC_EXCL
공유 메모리가 있으면 실패를 반환하고 접근하지 못하게 한다.
리턴값
1. int
공유 메모리의 shmid (shared memory ID)
2. -1
실패
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmAddr, int shmflg);
매개변수1 int shmid
공유 메모리 식별 변호
매개변수2 const void *shmAddr
붙여넣을 메모리 주소이며, 운영체제에서 자동으로 할당을 원할 경우 NULL로 지정한다.
매개변수3 int shmflg
추가 가능한 옵션
- SHM_RDONLY
공유 메모리를 읽기 전용으로 설정한다.
- SHM_RND
두번째 인자인 shmAddr 값이 NULL이 아닐 경우에만 쓴다. shmAddr을 반올림하여 메모리 경계에 맞춘다.
리턴값
1. void *
shmid에 대한 주소
2. -1
실패
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmAddr);
매개변수1 const void *shmAddr
분리할 공유 메모리의 주소
리턴값
1. 0
성공
2. -1
실패
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
매개변수1 int shmid
공유 메모리 식별 변호
매개변수2 int cmd
제어 명령
- IPC_RMID
지정된 공유 메모리 제거, 구조체 제거
- IPC_SET
공유 메모리 공간에 대한 사용자 권한을 변경한다.
- IPC_STAT
현재 공유 메모리 정보를 buf로 지정한 메모리에 저장한다.
- SHM_LOCK
공유 메모리 세그먼트를 잠근다.
- SHM_UNLOCK
공유 메모리 세그먼트를 잠금 해제한다.
매개변수3 struct shmid_ds *buf
공유 메모리 정보를 구하기 위한 버퍼포인터
struct shmid_ds {
struct ipc_perm shm_perm; /* 접근권한 */
int shm_segsz; /* 세그먼트의 크기(bytes) */
time_t shm_atime; /* 마지막 접근 시간 */
time_t shm_dtime; /* 마지막 제거 시간 */
time_t shm_ctime; /* 마지막 변경 시간 */
unsigned short shm_cpid; /* 생성자의 프로세스의 프로세스 id */
unsigned short shm_lpid; /* 마지막으로 작동한 프로세스의 프로세스 pid */
short shm_nattch; /* 현재 접근한 프로세스의 수 */
/* 다음은 개별적이다 */
unsigned short shm_npages; /* 세그먼트의 크기(pages) */
unsigned long *shm_pages;
struct shm_desc *attaches; /* 접근을 위한 기술자들 */
};
/* shm_perm 멤버의 필드들은 아래와 같이 설정할 수 있습니다. */
struct ipc_perm{
key_t key;
ushort uid; /* owner의 euid 와 egid */
ushort gid;
ushort cuid; /* 생성자의 euid 와 egid */
ushort cgid;
ushort mode; /* 접근 모드의 하위 9 bits */
ushort seq; /* 연속 수(sequence number) */
};
리턴값
1. 0
성공
2. -1
실패
#include <unistd.h>
int pipe(int pipefd[2]);
매개변수1 int pipefd[2]
크기가 2인 int형 배열
- pipefd[0]
읽기 전용 파이프 (파이프 출구, input stream)
함수 호출 후 fd[0]에 데이터를 입력 받을 수 있는 파일 디스크립터가 담김
- pipefd[1]
쓰기 전용 파이프 (파이프 입구, output stream)
함수 호출 후 데이터를 출력할 수 있는 파일 디스크립터가 담김
리턴값
1. 0
성공
2. -1
실패 errno
#include <fcntl.h>
#include <unistd.h>
int pipe2(int pipefd[2], int flags);
매개변수1 int pipefd[2]
크기가 2인 int형 배열
- pipefd[0]
읽기 전용 파이프 (파이프 출구, input stream)
함수 호출 후 fd[0]에 데이터를 입력 받을 수 있는 파일 디스크립터가 담김
- pipefd[1]
쓰기 전용 파이프 (파이프 입구, output stream)
함수 호출 후 데이터를 출력할 수 있는 파일 디스크립터가 담김
매개변수2 int flags
옵션
- O_CLOEXEC
열린 파일에 close-on-exec 플래그를 설정하고, 새 프로세스를 실행하면 이 파일은 자동으로 닫힌다
- O_DIRECT
’직접 입출력’을 수행하기 위해 파일을 오픈한다.
- O_NONBLOCK
파일을 논블로킹 모드로 오픈한다.
- 0
pipe()와 동일함
리턴값
1. 0
성공
2. -1
실패 errno
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
매개변수1 key_t key
시스템에서 식별하는 메시지 큐 번호
매개변수2 int msgflg
옵션
- IPC_CREAT
key에 해당하는 메시지 큐가 없으면 큐를 새로 생성하는데 이 때 접근 권한도 함께 부여해야 한다. 그러나 메시지 큐가 있으면 이 옵션은 무시한다.
- IPC_EXCL
메시지 큐가 있으면 실패라는 의미로 -1 반환. 이 값이 설정되지 않으면 기존 메시지 큐에 접근해 식별자를 반환한다.
리턴값
1. int
메시지 큐 식별자
2. -1
실패
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
매개변수1 int msqid
메시지 큐 식별자
매개변수2 const void *msgp
전송할 메시지
매개변수3 size_t msgz
메시지 크기
매개변수4 int msgflg
옵션
- IPC_NOWAIT
메시지 큐가 가득 차 있어 메시지를 더 이상 저장할 수 없을 경우 실패로 -1 반환. 이 값을 설정하지 않으면 메시지 큐가 메시지를 저장할 수 있을 때까지 대기
리턴값
1. 0
성공
2. -1
실패 errno
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
매개변수1 int msqid
메시지 큐 식별자
매개변수2 void *msgp
메시지를 수신할 곳 (메시지를 저장할 주소)
매개변수3 size_t msgz
메시지 크기
매개변수4 long msgtyp
메시지 타입
- 0
메시지 큐에서 첫번째 메시지를 수신
- 양수
메시지 큐에서 msgtyp으로 지정한 유형과 같은 메시지를 읽어온다.
- 음수
메시지 유형이 msgtyp으로 지정한 값의 절대값과 같거나 작은 메시지를 읽어온다.
- ex) 3개의 메시지 형식이 1, 5, 9 일 경우에, msgtyp가 -10일 경우 절대값 10보다 작거나 같은 메시지 형식을 갖는 메시지 모두 해당한다. 이 중 가장 작은 1 메시지 형식으로 갖고 있는 메시지 수신
매개변수5 int msgflg
옵션
- 0
블록 모드. 메시지가 올 때 까지 기다린다.
- IPC_NOWAIT
비블록 모두. 메시지 큐에 메시지가 없으면 실패로 -1 반환. 이 값을 설정하지 않으면 메시지가 큐에 도착할 때까지 대기
- MSG_NOERROR
메시지 크기가 msgsz보다 클 때 초과되는 부분을 자른다. 이 값을 설정하지 않으면 -1 반환.
리턴값
1. ssize_t
수신한 메시지 크기
성공하면, msqid_ds에서 msg_qnum이 1 감소, msg_lrpid는 msgrcv함수를 호출한 프로세스의 ID로 설정된다.
2. -1
실패 errno
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
매개변수1 int msqid
메시지 큐 식별자
매개변수2 int cmd
수행할 제어 기능
- IPC_STAT
현재 메시지 큐의 정보를 buf로 지정한 메모리에 저장함 msgctl(msqid, IPC_STAT, &buf);
- IPC_SET
메시지 큐의 정보를 buf에 저장한 값으로 변경. 단 msg_perm과 msg_qbtye멤버에 대한 정보만을 변경 가능. 변경은 root 또는 effective ID만 가능함 msgctl(msqid, IPC_SET, &buf);
- IPC_RMID
메시지 큐를 제거하고 관련 데이터 구조체를 제거한다. 이때 세번째 인수인 buf는 0으로 지정 msgctl(msqid, IPC_RMID, 0);
매개변수3 struct msqid_ds *buf
제어 기능에 사용되는 메시지 큐 구조체의 주소
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes in queue (nonstandard) */
msgqnum_t msg_qnum; /* Current number of messages in queue */
msglen_t msg_qbytes; /* Maximum number of bytes allowed in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
리턴값
1. 0
성공
2. -1
실패
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
매개변수1 const char *pathname
실제로 존재하고 access 가능한 파일 또는 디렉토리
- 상대 path이든 절대 path이든 실제로 같은 디렉토리
- 파일이면 pathname의 문자열이 달라도 같이 인식됨
- 파일이 존재해야 하는 이유는 stat으로부터 st_dev, st_ino를 얻기 위해서임
- ex) /usr/downman/data 와 ~/data가 실제 같은 디렉토리이면 같은 값임
매개변수2 int proj_id
같은 path에 대해 구분하기 위한 값으로 하위 8bit값만 사용됨 (1~255)
- 0은 사용할 수 없으며, 하위 8bit만 사용되므로 ‘M’, ‘S’ 등과 같이 문자를 사용할 수 있음
리턴값
1. key_t
0 이상
정상적으로 생성된 key값 (IPC 객체를 생성할 때 사용됨)
2. -1
실패 errno