System V IPC
System V IPC
System V IPC用の関数
メッセージキュー | セマフォ | 共有メモリ | |
ヘッダ | |||
作成、オープン、削除 | msgget | semget | shmget |
制御用関数 | msgctl | semctl | shmctl |
IPC操作用関数 | msgsnd, msgrcv | semop | shmat, shmdt |
key_tとftok関数
System V IPCは名前にkey_t(ftok関数は、既存のパス名と整数の正規別氏を、key_t値(IPCキー)に変換する。
#include <sys/ipc.h> key_t ftok(const char *pathname, int id); 戻り値:成功ならIPCキー、エラーなら-1
この関数は、pathnameとidの下位8ビットを組み合わせて整数のIPCキーを生成する。System V IPCを用いる特定のアプリケーションでは、そのアプリケーションにとってなんらかの意味があるpathnameを、サーバとクライアントの間で合意している必要がある。
一旦クライアントとサーバー間で、pathnameとidに関する合意が取れれば、両者は独立にftok関数を呼び出して、これらを同一のIPCキューに変換することが出来る。
//ftok関数のサンプル #include <stdio.h> #include <sys/ipc.h> int main() { key_t key; key = ftok("/tmp", 1); printf("IPC Key = %d\n", key); return 0; }
UNIX ネットワークプログラミング Vol.2 p.29の結果 Fedora5では、以下のようになった。 //ファイルシステムに関する情報と結果のIPCキーの印字 #include <stdio.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int main() { struct stat st; char *pathname = "/tmp"; stat(pathname, &st); printf("st_dev: %lx, st_ino: %lx, key: %x\n", (u_long)st.st_dev, (u_long)st.st_ino, ftok(pathname, 0x57)); return 0; } /////////////////////////////// //結果 st_dev: fd00, st_ino: 570001, key: 57000001
ipc_perm構造体
カーネルは、各IPCオブジェクトに関して、ファイルに関する情報と類似した情報の構造体を維持する
struct ipc_perm { uid_t uid; /* 所有者のユーザID */ gid_t gid; /* 所有者のグループID */ uid_t cuid; /* 作成者のユーザID */ gid_t cgid; /* 作成者のグループID */ mode_t mode; /* 読み書き許可ビット */ ulong_t seq; /* スロット使用シーケンス番号 */ key_t key; /* IPCキー */ };
この構造体を含め、他のSystem V IPC関数関連の主な定数は、
IPCチャネルの作成とオープン
IPCオブジェクトの作成あるいはオープンを行うmsgget(), semget(), shmget() は、すべてkey_t型のkey値を引数に持ち、整数の識別子を返す。アプリケーションは、msgget(), semget(), shmget() の最初の引数であるkey値に、次のいずれかを用いることが出来る。
IPCオブジェクトに関するIPC_CREATとIPC_EXCLの組み合わせは、open()におけるO_CREATとO_EXCLの組み合わせに類似している。
msgctl() : メッセージ制御操作
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl()はメッセージキュー識別子msqidで指定されたメッセージキューに対してcmdで指定された制御操作を行う。
msqid_dsデータ構造体は、
struct msqid_ds { struct ipc_perm msg_perm; /* 所有権と許可 */ time_t msg_stime; /* 最後のmsgsnd(2)の時刻 */ time_t msg_rtime; /* 最後のmsgrcv(2)の時刻 */ time_t msg_ctime; /* 最後に変更が行われた時刻 */ unsigned long __msg_cbytes; /* キューにある現在のバイト数 */ msgqnum_t msg_qnum; /* キューにある現在入っているメッセージの数 */ msglen_t msg_qbytes; /* キューに許可されている最大バイト数 */ pid_t msg_lspid; /* 最後のmsgsnd(2)のPID */ pid_t msg_lrpid; /* 最後のmsgrcv(2)のPID */ };
cmdの有効な値
msgget(), msgctl()サンプル
//カーネルが割り当てたメッセージキュー識別子を印字する #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int main() { int i, msqid; msqid = msgget(IPC_PRIVATE, IPC_CREAT); printf("msqid = %d\n", msqid); msgctl(msqid, IPC_RMID, NULL); return 0; } ///////////////////////// //結果 msqid = 360448
まとめ
参考文献:
UNIXネットワークプログラミング Vol.2 スティーブンズ
Linux manページ: http://www.linux.or.jp/JM/html/LDP_man-pages/man2/msgctl.2.html