3. メッセージキュー
3.1 System VのIPC
(1)System VのIPCの概要
基本的なプロセス間通信装置のプレゼンス信号機構と、名前付きパイプ、等①Unixパイプシステム。
②SystemVは、導入3つの高レベルのプロセス間通信機構:メッセージキューと共有共有セマフォを。
③IPCオブジェクトは、(メッセージキュー、セマフォ、共有メモリ)カーネル内に存在するのではなく、ファイルシステムであり、ユーザによって制御された放出(ユーザのライフサイクル管理対象IPC)、カーネルによって制御された放出導管とは異なり。
すべてのIPCを識別し、アクセスすることによって参照④IPCオブジェクトは、オブジェクトにカーネル空間固有の識別有するIDを、ユーザ空間での呼び出されたキーの一意の識別。
⑤LinuxIPCは、System V IPCから継承されました
アクセス(2)システムV IPCオブジェクト
:①IPCオブジェクトはグローバルオブジェクトで利用可能なIPCS、ビューまたは削除するpicrmコマンド。
msgget、たshmget、semgetから:②各IPCは、get関数によって作成されたオブジェクト。get関数を呼び出すときにキーワードのキーを指定する必要があります。
許可および構造の所有者(3)IPCオブジェクト
3.2 メッセージキュー
(1)はじめにメッセージキュー
①メッセージキューがあるカーネルのリンクリスト。
②カーネルにデータを転送するユーザー・プロセスは、カーネルは、ユーザID、グループIDとしてバック追加する、IDは、プロセスおよび優先順位に関する情報を読み取ると呼ばれるデータ・メッセージ・パケットにカプセル化されました。
③メッセージキューに書込みメッセージに1つ以上のプロセスを可能にし、メッセージを読み取るが、メッセージが唯一の方法であることができる読み取り、読み取りが自動的に終了した後に削除されます。
④メッセージキューはFIFO特定の特性を有する、順序は、いくつかの異なる方法がキューから読み取ることができ、メッセージ・キューに送信されてもよいです。各IPCメッセージはカーネルで表さ固有の識別IDをキュー。
⑤、メッセージキューは、aキューの作成と開口部を実装するメッセージを送信し、メッセージや制御メッセージキュー4つの操作をお読みください。
(2)メッセージ・キューの構造(れるmsqid_ds)
(3)オープンし、メッセージ・キューを作成します
ヘッダ |
書式#include <sysの/ msg.h> |
機能 |
INT msgget(key_tのキー、INTフラグ)。 |
パラメータ |
キー: メッセージキュー指定されたユーザキー 旗:IPC_CREAT、および権限の他の組み合わせIPC_EXCL |
機能 |
開くか、メッセージ・キューを作成します |
返却値 |
成功したリターンカーネルメッセージキュー識別子ID、エラー-1 |
リマーク |
①メッセージ・キューを作成するには、キーは、キーを指定することができ、それはまた、IPC_PRIVATEに設定することができます。 ②クエリを開くと、キーがゼロにすることはできません、それ以外の場合は、見つけることができない、ゼロ以外の値でなければなりません。 |
(4)制御メッセージキュー
ヘッダ |
書式#include <sysの/ msg.h> |
機能 |
int型はmsgctl(int型msgqid、int型CMD、構造体れるmsqid_ds * BUF)。 |
パラメータ |
msgqid :メッセージキューID BUF :ポインタメッセージキューの属性 CMD : (1)IPC_STAT:れるmsqid_dsはこのキューを構築取って、メッセージキューの属性を取得し、指定された構造bufに格納します。 (2)IPC_SET:設定特性は、尖った構造BUFの値に応じて、このフィールド構造に関連付けられたキューを提供しました。 (3)IPC_RMID:キューを削除し、メッセージキュー、すべてのデータがシステムからキューに残っている削除します。 |
機能 |
制御メッセージキュー |
返却値 |
0を返す成功し、エラー-1 |
(5)メッセージを送信します。
ヘッダ |
書式#include <sysの/ msg.h> |
機能 |
int型にmsgsnd(int型msgqid、CONST void *型PTR、size_tのnbytesは、int型のフラグ); |
パラメータ |
msqid :メッセージキューID PTR :ユーザー定義の構造が、最初のメンバーはMTYPEでなければなりません。 構造体mymesg { 長いMTYPE; //正のメッセージ・タイプ、メッセージ・タイプ、およびのみ0以上の整数を大きくすることができます。 チャーマルチテキスト[512]; //メッセージ・データ、長さnバイトのメッセージデータそのもの } nバイト:指定したメッセージのサイズは、MTYPEのサイズが含まれていません。 フラグ: (1)0、ブロックされました。(2)IPC_NOWAIT:ファイルI / Oの非ブロッキングI / Oフラグと同様。 (3)メッセージ・キューが満杯を有する(またはバイトの総数がシステムに等しく、システムメッセージキュー制限、またはキュー制限の総数に等しい)直ちにエラーEAGAINを返すようにmsgsnd指定IPC_NOWAITを使用して、場合。0を指定すると、空間までプロセス:. Aブロックは、送信するメッセージに対応することができます。B.キューまたは削除システムから;. C又は信号と戻り信号ハンドラを取り込みます。 |
機能 |
メッセージを送ります |
返却値 |
0を返す成功し、エラー-1 |
リマーク |
Linuxでは、メッセージの最大長は4つのバイトを占有MTYPE、を含む4056バイトです。 |
(6)メッセージを受信します
ヘッダ |
書式#include <sysの/ msg.h> |
機能 |
int型のmsgrcv(int型msgqid、無効* ptrは、size_tのnbytesは、int型のフラグ); |
パラメータ |
msqid :メッセージキューID PTR :ストアのメッセージへのバッファへのポイント nバイト:メッセージバッファのサイズは、サイズがMTYPEが含まれていません。計算値: nバイト=はsizeof(構造体mymesg) - はsizeof(長いです)。 type:消息类型 (1)type == 0:获取消息队列中的第一个消息 (2)type > 0: 获取消息队列中类型为type的第一个消息 (3)type < 0: 获取消息队列中小于或等于type绝对值的消息(类型最小的) flag:0或IPC_NOWAIT |
功能 |
接收消息 |
返回值 |
成功返回消息的数据部分长度,出错返回-1 |
【编程实验】消息队列
//msq_snd.c //发送进程(要单独编译成一个可执行文件)
#include <stdio.h> #include <stdlib.h> #include <sys/msg.h> //消息结构体 typedef struct{ long type; //消息类型 int start; //消息数据本身(包括start和end) int end; }MSG; /*往消息队列中发送消息*/ int main(int argc, char* argv[]) { //从命令行中转入消息的key if(argc < 2){ printf("usage: %s key\n", argv[0]); exit(1); } key_t key = atoi(argv[1]);//key由用户指定,如10 //key_t key = IPC_PRIVATE; //key由系统指定 //key_t key = ftok(argv[0], 0);//要据文件名和第2个参数生成key printf("key: %d\n", key); //创建或获取消息队列 int msq_id; //IPC_CREAT | IPC_EXCL:不存在则创建,存在时返回错误!(保证对象总是新的) //而不是打开己有的对象 if((msq_id = msgget(key, IPC_CREAT | IPC_EXCL | 0777)) < 0){ perror("msgget error"); } printf("msq id: %d\n", msq_id); //定义要发送的消息 MSG mArr[5] ={ {4, 4, 100}, {2, 2, 200}, {1, 1, 100}, {6, 6, 600},//注意两条type都等于6的消息。 {6, 60, 6000} }; //发送消息到消息队列 int i = 0; for(; i<5; i++){ if(msgsnd(msq_id, &mArr[i], sizeof(MSG)-sizeof(long), IPC_NOWAIT) < 0){ perror("msgsnd error"); } } //发送后获得消息队列中消息的总数 struct msqid_ds ds={0}; if(msgctl(msq_id, IPC_STAT, &ds) < 0){ perror("msgctl error"); } printf("msg total: %d\n", ds.msg_qnum); return 0; } /*输出结果: [root@localhost 11.IPC]# bin/msq_snd 10 //其中的key(10)由用户指定 key: 10 msq id: 65536 msg total: 5 [root@localhost 11.IPC]# ipcs -q //查看消息队列 ------ Message Queues -------- //可以看出有5种消息 key msqid owner perms used-bytes messages 0x0000000a 65536 root 777 40 5 [root@localhost 11.IPC]# ipcrm -q 65536 //删除指定的消息队列 [root@localhost 11.IPC]# ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages */
//msg_rcv.c //接收进程(要单独编译成一个可执行文件)
#include <sys/msg.h> #include <stdio.h> #include <stdlib.h> typedef struct{ long type; int start; int end; }MSG; int main(int argc, char* argv[]) { if(argc < 3){ printf("usage: %s key type\n", argv[0]); exit(1); } key_t key = atoi(argv[1]); long type = atoi(argv[2]); //获得指定的消息队列 int msq_id; if((msq_id = msgget(key, 0777)) < 0){ perror("msgget error"); } printf("msg id: %d\n", msq_id); MSG m; if(msgrcv(msq_id, &m, sizeof(MSG)-sizeof(long), type, IPC_NOWAIT) < 0){ perror("msgrcv error"); }else{ printf("type: %d start: %d end: %d\n", m.type, m.start, m.end); } return 0; } /*输出结果: [root@localhost 11.IPC]# bin/msq_snd 10 //send进程,先创建消息队列 key: 10 msq id: 262144 msg total: 5 [root@localhost 11.IPC]# bin/msq_rcv 10 1 //receive进程,从key队列中获得type为1的消息 msg id: 262144 type: 1 start: 1 end: 100 [root@localhost 11.IPC]# bin/msq_rcv 10 2 //获取type为2的消息 msg id: 262144 type: 2 start: 2 end: 200 [root@localhost 11.IPC]# bin/msq_rcv 10 3 //获取type为3的消息(不存在的消息) msg id: 262144 msgrcv error: No message of desired type //获取type为4的消息 [root@localhost 11.IPC]# bin/msq_rcv 10 4 msg id: 262144 type: 4 start: 4 end: 100 [root@localhost 11.IPC]# bin/msq_rcv 10 6 //获取类型为6的第1条消息(先进先出) msg id: 262144 type: 6 start: 6 end: 600 [root@localhost 11.IPC]# bin/msq_rcv 10 6 //获取类型为6的第2条消息 msg id: 262144 type: 6 start: 60 end: 6000 [root@localhost 11.IPC]# ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x0000000a 262144 root 777 0 0 [root@localhost 11.IPC]# ipcrm -q 262144 [root@localhost 11.IPC]# ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages */