第11章プロセス間通信(2)_メッセージキュー

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  
 */

复制代码

发布了25 篇原创文章 · 获赞 4 · 访问量 2万+

おすすめ

転載: blog.csdn.net/zhou8400/article/details/97392295