Advanced IPC facilities
IPC는 프로세스간 정보교환의 매커니즘을 제공한다.
IPC는 다음과 같은 세 가지로 이루어져 있다.
message queues는 pipe와 비슷한 개념이다.
semaphores는 변수를 공유할 때 프로세스 간 동기(synchronization)를 맞추는 역할을 한다.
shared memory는 프로세스간 변수 즉 메모리를 공유할 수 있도록 도와준다.
message queue와 semaphore는 file을 사용하는 방법과 유사하다.
file | message queue | semaphore | shared memory |
file name : “filename” | key : key_t | key : key_t | key : key_t |
file descriptor : int | identifier : int | identifier : int | identifier : int |
open() | msqget() | semget() | shmget() |
fcntl() | msqctl() | semctl() | shmctl() |
struct stat (i-node 구조) |
struct msqid_ds | struct semid_ds | struct shmid_ds |
read() | msqrcv() message queue receive |
- | - |
write() | msqsnd() message queue send |
- | - |
- | - | semop() | - |
- | - | - | shmat() (shared memory attach) |
- | - | - | shmdt() (shared memory detach) |
위 표에서와 같이 file에서 사용하는 각각의 요소들에 대응하는 것들이 있다.
Permission Structure
file의 i-node의 경우 struct stat안에 st_mode로 permission을 관리했듯,
msq(message queue), sem(semaphore), shm(shared memory)에 각각 해당하는 msqid_ds, semid_ds, shmid_ds에 모두 ipc_perm이 존재한다.
struct ipc_perm {
uid_t uid; /* owner's effective user id */
gid_t gid; /* owner's effective group id */
uid_t cuid; /* creator's effective user id */
gid_t cgid; /* creator's effective group id */
mode_t mode; /* access modes */
…
}; /* a field of xxx_ds */
ipc_perm에는 st_mode 같은 역할의 mode가 있어 mode를 통해 permission을 관리한다.
IPC에는 이와 같이 read, write만이 필요하고 execute bit는 사용하지 않는다.
- uid, gid의 경우 owner의 id이고, cuid, cgid는 creator의 id이다.
creator는 생성한 프로세스의 euid이고, owner의 경우 creator와 같지만, owner를 변경하는 경우도 있다.
- IPC facility를 생성할 때 umask는 영향을 미치지 않는다.
- uid, gid, mode는 msgctl, semctl, shmctl 을 호출함으로써 변경할 수 있다. (creator 또는 superuser만 가능)
Identifiers and Keys
IPC에서는 file의 filename에 해당되는 것이 key이다.
key
IPC object에서 External name으로 사용된다.
IPC structure가 msgget, semget, shmget등으로 생성될 때, key가 특정되어야 한다.
key는 <sys/types.h>에 key_t(long integer)라는 data type으로 정의되어 있다.
Identifier
IPC object에서 Internal name으로 된다.
non-negative integer이며, get 연산들 (msgget, semget, shmget)의 return값이다.
file descriptor처럼 행동하지만, file descriptor와는 달리 IPC facility identifier가 unique하다.
즉 다른 프로세스에서 같은 IPC object에 대해 같은 값을 사용한다.
The ftok(2) system call
#include <sys/ipc.h>
key_t ftok(const char *path, int id);
// Returns: key if OK, (key_t)-1 on error
filename은 같을 수 있지만, absloute pathname은 unique하다.
하지만 Identifier의 key는 직접설정하므로 unique하지 않을 수 있다. 그래서 unique한 key를 생성하지 위한 역할을 하는 것이 ftok이다.
path와 자신만의 id를 통해서 key_t를 생성하여 반환한다(path와 id가 모두 같은 경우에는 같은 키가 생성). path는 존재하는 file, id는 lower 8 bit 즉 0~255의 수를 이용한다.
if ((thekey = ftok("tmp/trouble.c", 1)) == (key_t)-1))
perror("Failed to derive key from /tmp/trouble.c");
위와 같이 사용하여 path와 id의 조합인 key로 unique한 IPC object를 식별하게 한다.
path가 존재하지 않거나 호출하는 process에 접근할 수 없으면 ftok은 -1를 return한다.
IPC get operations
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
int msgget(key_t key, int permflags);
int semget(key_t key, int nsems, int permflags);
int shmget(key_t key, size_t size, int permflags);
// Returns: identifier if OK, -1 on error
get은 key를 매개변수로 하여 identifies를 반환한다. permflags를 통해 permission을 준다.
semaphore의 경우 nsems는 semaphore set에 들어갈 semaphore의 개수이다.
sharedmemory의 size는 share하는 memory의 크기를 의미한다.
get함수의 key값을 주는 방법은 다음과 같이 3가지가 있다.
- IPC_PRIVATE 상수, 즉 key 선택 시스템을 이용한다. (셋 중 100% unique)
- key값을 직접 지정한다.
- ftok을 통해 key값을 생성한다.
permflags의 경우 IPC전용으로 옵션들이 다음과 같은 방식으로 있다.
- IPC_CREAT → O_CREAT
- IPC_EXCL → O_EXCL
CREAT는 file이 없으면 get, EXCL은 file이 있다면 error 등 기존 옵션들과 내용은 일치한다.
header <sys/msg.h>, <sys/sem.h>, <sys/shm.h> 에 포함된 IPC permission은 다음과 같다.
Numeric (octal) |
Symbolic values | Description | ||
Message queue |
Semaphore | Shared memory |
||
0400 0200 |
MSG_R MSG_W |
SEM_R SEM_A |
SHM_R SHM_W |
user-read user-write (alter) |
0040 0020 |
MSG_R >> 3 MSG_W >> 3 |
SEM_R >> 3 SEM_A >> 3 |
SHM_R >> 3 SHM_W >> 3 |
group-read group-write (alter) |
0004 0002 |
MSG_R >> 6 MSG_W >> 6 |
SEM_R >> 6 SEM_A >> 6 |
SHM_R >> 6 SHM_W >> 6 |
other-read other-write (alter) |
semaphore의 _A는 alter의 A로 write와 의미상 같다.
IPC의 permission에는 execute에 해당하는 permission은 없다.
IPC ctl operations
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
int msgctl(int msqid, int command, struct msqid_ds *buf );
int semctl(int semid, int semnum, int command,…/*union semun arg*/);
int shmctl(int shmid, int command, struct shmid_ds *buf);
// Returns: 0 if OK, -1 on error
ctl은 file의 fcntl 및 stat 명령어를 한 번에 하는 명령어이다.
get을 통해 얻은 id를 매개변수로 하며, command 매개변수를 통해 작업할 명령어를 전달한다.
command의 종류는 다음과 같다.
command | description |
IPC_STAT | Return the referenced IPC resource status information. When specifying IPC_STAT, the ctl system call must pass a pointer to an allocated structure of the appropriate type to store the returned information struct msgid_ds, semid_ds, shmid_ds와 같은 status info struct를 반환한다. |
IPC_SET | Change the owner, group, or mode for the IPC resource. In addition, as with IPC_STAT, a pointer to a structure of the appropriate type (with the changed member information) must be passed IPC_STAT로 가져온 정보 중 일부를 변경할 수 있다. |
IPC_RMID | Destroy the contents of the IPC resource and remove it from the system id가 가리키는 IPC object를 remove 한다. |
Generating IPC indentifiers from IPC keys
ftok, IPC_PRIVATE, user-define의 세 방식으로 key를 지정하고,
key를 매개변수로 get를 실행하여 id를 얻는다.
얻은 id를 통해 ctl, send, receive, attach 등 각종 명령어를 사용한다.
Accessing IPC resources from the shell
SYNOPSIS
ipcs [-qms][-a | -bcopt]
ipcrm [-q msgid | -Q msgkey | -s semid | -S semkey |
-m shmid | -M shmkey] ....
// POSIX:XSI,Shell and Utilities
ipcs (ipc status) 명령어로 IPC에 대한 정보를 command line에서 확인할 수 있다.
ipcrm 명령어로 command line에서 IPC object를 삭제할 수 있다.
$ ipcs
------ Shared Memory Segments ------
key shmid owner perms bytes nattch status
0x00000000 25198594 root 666 247264 3
------ Semaphore Arrays ------
key semid owner perms nsems status
0x00000000 65537 root 666 4
0x00000000 98306 root 666 16
0x00000000 131075 root 666 16
0x00000000 163844 root 666 16
------ Message Queues ------
key msqid owner perms used-bytes messages
$ ipcrm –s 65537
$ ipcrm -q 25198594
ipcs 명령어를 사용한 결과는 위와 같다. 옵션없이 실행하면 shared memory, semaphore, message queue의 각종 정보를 알 수 있다.
ipcrm명령어를 통해 semaphore, message queue를 삭제하는 것을 확인할 수 있다.