ホームページ  >  記事  >  システムチュートリアル  >  Linux IPC System V メッセージ キュー: 信頼性の高いメッセージ配信のための古典的な方法

Linux IPC System V メッセージ キュー: 信頼性の高いメッセージ配信のための古典的な方法

王林
王林転載
2024-02-12 15:33:151135ブラウズ

Linux システムは、マルチタスクの同時実行をサポートするオペレーティング システムであり、複数のプロセスを同時に実行できるため、システムの使用率と効率が向上します。ただし、これらのプロセス間でデータ交換とコラボレーションが必要な場合は、シグナル、共有メモリ、セマフォなどのプロセス間通信 (IPC) メソッドを使用する必要があります。その中でも、System V メッセージ キューは比較的古典的で信頼性の高い IPC 方式であり、2 つ以上のプロセスがメッセージの内容や形式を気にせずにキューを介してメッセージを送信できます。この記事では、メッセージ キューの作成、オープン、送信、受信、クローズ、削除など、Linux システムでの System V メッセージ キューの方法を紹介します。

Linux IPC System V 消息队列:一种实现可靠消息传递的经典方式

######モデル###### リーリー

ftok()

リーリー

pathname: ファイル名

proj_id: project_id を表す 1 ~ 255 の数字 リーリー
msgget()

リーリー

msgflg: 特定の操作フラグ

IPC_CREAT

存在しない場合は作成します。msgflg に「|権限情報」を設定する必要があります。存在する場合はそれを開きます
  • IPC_EXCL存在する場合、作成は失敗します
  • 0 既存のメッセージ キューを取得します
  • メッセージ キューの容量は msg_qbytes によって制御されます。メッセージ キューの作成プロセス中に、このサイズは MSGMNB に初期化されます。この制限は msgctl() を通じて変更できます リーリー
msgsnd()

リーリー

msqid msgget()で返されるメッセージキューのID

msgpメッセージの先頭アドレス、メッセージの参照データ型は以下のとおりです リーリー
msgszメッセージのサイズ。このパラメータは、メッセージの種類を除く、メッセージ内容のサイズを指定するために使用されます。 sizeof(Msgbuf) ではなく、sizeof(Msgbuf.mtext) のみです。

msgflg送信されるフラグ。デフォルトは 0 リーリー
msgrcv()

リーリー

msqid: メッセージ キューの ID (msgget によって返される)

msgp: 受信したメッセージが格納されるバッファーの最初のアドレス
msgsz : メッセージの種類を除く、メッセージの最大サイズ ==>sizeof(Msgbuf) ではなく、sizeof(Msgbuf.mtext) のみです。
メッセージの長さが >msgsz で、msgflg に MSG_NOERROR がある場合、メッセージは切り詰められ、切り詰められた部分は失われます

メッセージの長さが > msgsz で、msgflg に MSG_NOERROR がない場合、エラーが発生し、E2BIG が報告されます。
  • msgtyp: メッセージの種類

0:メッセージキューの最初のメッセージを読み取ります

  • #>>0: メッセージ キュー内の msgtype タイプの最初のメッセージを読み取ります。msg_flg に MSG_EXCEPT がない限り、msgtyp ではないキュー内の最初のメッセージが読み取られます
  • #Read type
  • をメッセージ キューに入力します
  • msgflg: 送信するフラグ、デフォルトは 0
    Msg msg1;
    int res=msgrcv(msqid,&msg1,sizeof(msg1.buf),1,0);
    if(-1==res)
        perror("msgrcv"),exit(-1);
    

    msgctl()

    // 消息操作,成功返回0,失败返回-1设errno
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    

    msqid :消息队列的ID,由msgget()
    buf 结构体指针

    struct msqid_ds {
        struct ipc_perm msg_perm;       /* Ownership and permissions */
        time_t          msg_stime;      /*Time of last msgsnd(2) */
        time_t          msg_rtime;      /* Time of last msgrcv(2) */
        time_t          msg_ctime;      /* Time of last change */
        unsigned long   __msg_cbytes;   /* Current number of bytes in queue (nonstandard) */
        msgqnum_t       msg_qnum;       /* Current number of messages in queue */
        msglen_t        msg_qbytes;     /* Maximum number of bytes allowed in queue */
        pid_t           msg_lspid;      /* PID of last msgsnd(2) */
        pid_t           msg_lrpid;      /* PID of last msgrcv(2) */
    };
    struct ipc_perm {
        key_t           __key;      /* Key supplied to msgget(2) */
        uid_t           uid;        /* Effective UID of owner */
        gid_t           gid;        /* Effective GID of owner */
        uid_t           cuid;       /* Effective UID of creator */
        gid_t           cgid;       /* Effective GID of creator */
        unsigned short  mode;       /* Permissions */
        unsigned short  __seq;      /* Sequence number */
    };
    

    cmd

    • IPC_STAT从内核相关结构体中拷贝消息队列相关的信息到buf指向的结构体中

    • IPC_SET把buf指向的结构体的内容写入到内核相关的结构体中,同时更显msg_ctimer成员,同时以下成员也会被更新:msg_qbytes, msg_perm.uid, msg_perm.gid, msg_perm.mode。调用队列的进程的effective UID必须匹配队列所有者或创建者的msg_perm.uid或msg_perm.cuid或者该进程拥有特权级别,

    • IPC_RMID立即销毁消息队列,唤醒所有正在等待读取或写入该消息队列进程,调用的进程的UID必须匹配队列所有者或创建者或者该进程拥有足够的特权级别

    • IPC_INFO (Linux-specific)返回整个系统对与消息队列的限制信息到buf指向的结构体中

      //_GNU_SOURCE
      //
      struct msginfo {
          int msgpool;/*Size in kibibytes of buffer pool used to hold message
       data; unused within kernel*/
          int msgmap; /*Maximum number of entries in message map; unused within 
      kernel*/
          int msgmax; /*Maximum number of bytes that can be written in a single
       message*/
          int msgmnb; /*Maximum number of bytes that can be written to queue; 
      used to initialize msg_qbytes  during queue creation*/
          int msgmni; /*Maximum number of message queues*/
          int msgssz; /*Message segment size; unused within kernel*/
          int msgtql; /*Maximum number of messages on all queues in system; unused
       within kernel*/
          unsigned short int  msgseg; /*Maximum number of segments; unused
       within kernel*/
      };
      
      int res=msgctl(msqid,IPC_RMID,NULL);
      if(-1==res)
      perror("msgctl"),exit(-1);
      

    例子

    //Sys V IPC msg
    #include
    #include
    #include
    #include
    #include
    typedef struct{
        long mtype;     //消息的类型
        char buf[20];       //消息的内容
    }Msg;
    int msqid;          //使用全局变量,这样就可以在fa中使用msqid了
    void fa(int signo){
        printf("deleting..\n");
        sleep(3);
        int res=msgctl(msqid,IPC_RMID,NULL);
        if(-1==res)
            perror("msgctl"),exit(-1);
        exit(0);
    }
    int main(){
        //ftok()
        key_t key=ftok(".",150);
        if(-1==key)
            perror("ftok"),exit(-1);
        printf("key%#x\n",key);
        //msgget()
        msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664);
        if(-1==msqid)
            perror("msgget"),exit(-1);
        printf("msqid%d\n",msqid);
        //msgsnd()
        Msg msg1={1,"hello"};//消息的类型是1,内容是hello
        Msg msg2={2,"world"};
        int res=msgsnd(msqid,&msg2,sizeof(msg2.buf),0);
        if(-1==res)
            perror("msgsnd"),exit(-1);
        res=msgsnd(msqid,&msg1,sizeof(msg1.buf),0);
        if(-1==res)
            perror("msgsnd"),exit(-1);
        //msgctl()
        //Ctrl+C delete msq
        printf("Press CTRL+C to delete msq\n");
        if(SIG_ERR==signal(SIGINT,fa))
            perror("signal"),exit(-1);
        while(1);
        return 0;
    }
    

    本文介绍了Linux系统中System V 消息队列的方法,包括消息队列的创建、打开、发送、接收、关闭和删除等方面。通过了解和掌握这些知识,我们可以更好地使用System V 消息队列来实现进程间通信,提高系统的稳定性和效率。当然,Linux系统中System V 消息队列还有很多其他的特性和用法,需要我们不断地学习和研究。希望本文能给你带来一些启发和帮助。

以上がLinux IPC System V メッセージ キュー: 信頼性の高いメッセージ配信のための古典的な方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlxlinux.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。