#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
key の値が IPC_PRIVATE の場合、もしくは semflg に IPC_CREAT が指定されていて、 key に対応するセマフォ集合が存在しない場合、 nsems 個のセマフォからなる新しい集合が作成される。
semflg に IPC_CREAT と IPC_EXCL の両方が指定された場合、 key に対応するセマフォ集合が既に存在すると、 semget() は失敗し、 errno に EEXIST が設定される (これは open(2) に O_CREAT | O_EXCL が指定された場合の動作と同じである)。
セマフォ集合作成時に、引数 semflg の下位 9 ビットは、そのセマフォ集合の (所有者 (owner)、グループ (group)、 他人 (others) に対する) アクセス許可の定義として使用される。 これらのビットは open(2) の引数 mode と同じ形式で同じ意味である (但し、実行 (execute) 許可はセマフォでは意味を持たず、 書き込み (write) 許可はセマフォ値の変更 (alter) 許可として機能する)。
新規のセマフォ集合を作成する際、 semget() はセマフォ集合の情報を保持するデータ構造体 semid_ds を次のように初期化する (semid_ds については semctl(2) を参照):
セマフォ集合の作成を行わない場合は、引数 nsems に (don't care を意味する) 0 を指定してもよい。 そうでない場合は、 nsems は 0 より大きい値でなければならず、セマフォ集合あたりのセマフォの最大数 (SEMMSL) 以下でなければならない。
セマフォ集合が既に存在した場合は、アクセス許可の検査が行われる。
IPC_PRIVATE はフラグフィールドに指定するものではなく、 key_t 型である。 この特別な値が key に指定されると、 semget() semflg の下位 9 ビット以外は全て無視し、 (成功した場合は) 新しいセマフォ集合を作成する。
semctl(2) の SETVAL か SETALL 操作を使って初期化することができる。 複数箇所からセマフォ集合の操作が行われる場面では、 誰が最初に集合を初期化すればよいか分からない。 この状況を避けるには、 semctl(2) の IPC_STAT 操作で取得できるセマフォのデータ構造体の sem_otime が 0 以外になっているかをチェックすればよい。
We first create two files that will be used to generate keys using ftok(3), create two semaphore sets using those files, and then list the sets using ipcs(1):
$ touch mykey mykey2 $ ./t_semget -c mykey p 1 ID = 9 $ ./t_semget -c mykey2 p 2 ID = 10 $ ipcs -s
------ Semaphore Arrays -------- key semid owner perms nsems 0x7004136d 9 mtk 600 1 0x70041368 10 mtk 600 2
Next, we demonstrate that when semctl(2) is given the same key (as generated by the same arguments to ftok(3)), it returns the ID of the already existing semaphore set:
$ ./t_semget -c mykey p 1 ID = 9
Finally, we demonstrate the kind of collision that can occur when ftok(3) is given different pathname arguments that have the same inode number:
$ ln mykey link $ ls -i1 link mykey 2233197 link 2233197 mykey $ ./t_semget link p 1 # Generates same key as 'mykey' ID = 9
Licensed under GNU General Public License v2 or later. */ #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>
static void usage(const char *pname) {
fprintf(stderr, "Usage: %s [-cx] pathname proj-id num-sems\n",
pname);
fprintf(stderr, " -c Use IPC_CREAT flag\n");
fprintf(stderr, " -x Use IPC_EXCL flag\n");
exit(EXIT_FAILURE); }
int main(int argc, char *argv[]) {
int semid, nsems, flags, opt;
key_t key;
flags = 0;
while ((opt = getopt(argc, argv, "cx")) != -1) {
switch (opt) {
case 'c': flags |= IPC_CREAT; break;
case 'x': flags |= IPC_EXCL; break;
default: usage(argv[0]);
}
}
if (argc != optind + 3)
usage(argv[0]);
key = ftok(argv[optind], argv[optind + 1][0]);
if (key == -1) {
perror("ftok");
exit(EXIT_FAILURE);
}
nsems = atoi(argv[optind + 2]);
semid = semget(key, nsems, flags | 0600);
if (semid == -1) {
perror("semget");
exit(EXIT_FAILURE);
}
printf("ID = %d\n", semid);
[man1]
[man2]
[man3]
[man4]
[man5]
[man6]
[man7]
[man8]
[a]
[b]
[c]
[d]
[e]
[f]
[g]
[h]
[i]
[j]
[k]
[l]
[m]
[n]
[o]
[p]
[q]
[r]
[s]
[t]
[u]
[v]
[w]
[x]
[y]
[z]