zoukankan      html  css  js  c++  java
  • 消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例

    消息队列常用命令:

    ipcs -q  

    ipcs -l

    ipcrm -q

    消息队列函数由msgget、msgctl、msgsnd、msgrcv四个函数组成。下面的表格列出了这四个函数的函数原型及其具体说明。

    1.   msgget函数原型

    如果用msgget创建了一个新的消息队列对象时,则msqid_ds结构成员变量的值设置如下:

            msg_qnum、msg_lspid、msg_lrpid、 msg_stime、msg_rtime设置为0。

            msg_ctime设置为当前时间。

            msg_qbytes设成系统的限制值。

            msgflg的读写权限写入msg_perm.mode中。

            msg_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被设置成当前进程的有效组ID。

    2.   msgctl函数原型

    3.   msgsnd函数原型

       msgsnd()为阻塞函数,当消息队列容量满或消息个数满会阻塞。消息队列已被删除,则返回EIDRM错误;被信号中断返回E_INTR错误。

     如果设置IPC_NOWAIT消息队列满或个数满时会返回-1,并且置EAGAIN错误。

    msgsnd()解除阻塞的条件有以下三个条件:

    ①    不满足消息队列满或个数满两个条件,即消息队列中有容纳该消息的空间。

    ②    msqid代表的消息队列被删除。

    ③    调用msgsnd函数的进程被信号中断。

    4.   msgrcv函数原型

    msgrcv()解除阻塞的条件有以下三个:

    ①    消息队列中有了满足条件的消息。

    ②    msqid代表的消息队列被删除。

    ③    调用msgrcv()的进程被信号中断。

    消息队列使用程序范例

    5.   消息队列控制范例
    msgctl.c源代码如下:

    #include <stdio.h>

    #include <string.h>

    #include <unistd.h>

    #include <sys/ipc.h>

    #include <sys/msg.h>

    #include <error.h>

    #define TEXT_SIZE  512

    struct msgbuf

    {

        long mtype ;

        char mtext[TEXT_SIZE] ;

    }  ;

    int main(int argc, char **argv)

    {

        int msqid ;

        struct msqid_ds info ;

        struct msgbuf buf ;

        struct msgbuf buf1 ;

        int flag ;

        int sendlength, recvlength ;

        msqid = msgget( IPC_PRIVATE, 0666 ) ;

        if ( msqid < 0 )

        {

            perror("get ipc_id error") ;

            return -1 ;

        }

        buf.mtype = 1 ;

        strcpy(buf.mtext, "happy new year!") ;

        sendlength = sizeof(struct msgbuf) - sizeof(long) ;

        flag = msgsnd( msqid, &buf, sendlength , 0 ) ;

        if ( flag < 0 )

        {

            perror("send message error") ;

            return -1 ;

        }

        buf.mtype = 3 ;

        strcpy(buf.mtext, "good bye!") ;

        sendlength = sizeof(struct msgbuf) - sizeof(long) ;

        flag = msgsnd( msqid, &buf, sendlength , 0 ) ;

        if ( flag < 0 )

        {

            perror("send message error") ;

            return -1 ;

        }

        flag = msgctl( msqid, IPC_STAT, &info ) ;

        if ( flag < 0 )

        {

            perror("get message status error") ;

            return -1 ;

        }

        printf("uid:%d, gid = %d, cuid = %d, cgid= %d " ,

            info.msg_perm.uid,  info.msg_perm.gid,  info.msg_perm.cuid,  info.msg_perm.cgid  ) ;

        printf("read-write:%03o, cbytes = %lu, qnum = %lu, qbytes= %lu " ,

            info.msg_perm.mode&0777, info.msg_cbytes, info.msg_qnum, info.msg_qbytes ) ;

        system("ipcs -q") ;

        recvlength = sizeof(struct msgbuf) - sizeof(long) ;

        memset(&buf1, 0x00, sizeof(struct msgbuf)) ;

        flag = msgrcv( msqid, &buf1, recvlength ,3,0 ) ;

        if ( flag < 0 )

        {

            perror("recv message error") ;

            return -1 ;

        }

        printf("type=%d, message=%s ", buf1.mtype, buf1.mtext) ;

        flag = msgctl( msqid, IPC_RMID,NULL) ;

        if ( flag < 0 )

        {

            perror("rm message queue error") ;

            return -1 ;

        }

        system("ipcs -q") ;

       return 0 ;

    }

    编译 gcc msgctl.c –o msgctl。

    执行 ./msg,执行结果如下:

    uid:1008, gid = 1003, cuid = 1008, cgid= 1003

    read-write:666, cbytes = 1024, qnum = 2, qbytes= 163840

    ------ Message Queues --------

    key        msqid      owner      perms      used-bytes   messages   

    0x00000000 65536      zjkf       666        1024         2          

    type=3, message=good bye!

    ------ Message Queues --------

    key        msqid      owner      perms      used-bytes   messages  

    6.  两进程通过消息队列收发消息
    (1)发送消息队列程序

    msgsnd.c源代码如下:

    #include <stdio.h>

    #include <string.h>

    #include <unistd.h>

    #include <sys/ipc.h>

    #include <sys/msg.h>

    #include  <time.h>

    #define TEXT_SIZE  512

    struct msgbuf

    {

        long mtype ;

        int  status ;

        char time[20] ;

        char mtext[TEXT_SIZE] ;

    }  ;

    char  *getxtsj()

        time_t  tv ;

        struct  tm   *tmp ;

        static  char  buf[20] ;

        tv = time( 0 ) ;

        tmp = localtime(&tv) ;

        sprintf(buf,"%02d:%02d:%02d",tmp->tm_hour , tmp->tm_min,tmp->tm_sec);

        return   buf ;

    }

    int main(int argc, char **argv)

    {

        int msqid ;

        struct msqid_ds info ;

        struct msgbuf buf ;

        struct msgbuf buf1 ;

        int flag ;

        int sendlength, recvlength ;

        int key ;

        key = ftok("msg.tmp", 0x01 ) ;

        if ( key < 0 )

        {

            perror("ftok key error") ;

            return -1 ;

        }

        msqid = msgget( key, 0600|IPC_CREAT ) ;

        if ( msqid < 0 )

        {

            perror("create message queue error") ;

            return -1 ;

        }

        buf.mtype = 1 ;

        buf.status = 9 ;

        strcpy(buf.time, getxtsj()) ;

        strcpy(buf.mtext, "happy new year!") ;

        sendlength = sizeof(struct msgbuf) - sizeof(long) ;

        flag = msgsnd( msqid, &buf, sendlength , 0 ) ;

        if ( flag < 0 )

        {

            perror("send message error") ;

            return -1 ;

        }

        buf.mtype = 3 ;

        buf.status = 9 ;

        strcpy(buf.time, getxtsj()) ;

        strcpy(buf.mtext, "good bye!") ;

        sendlength = sizeof(struct msgbuf) - sizeof(long) ;

        flag = msgsnd( msqid, &buf, sendlength , 0 ) ;

        if ( flag < 0 )

        {

            perror("send message error") ;

            return -1 ;

        }

        system("ipcs -q") ;

       return 0 ;

    }

    (2)接收消息队列程序

    msgrcv.c源代码如下:

    #include <stdio.h>

    #include <string.h>

    #include <unistd.h>

    #include <sys/ipc.h>

    #include <sys/msg.h>

    #define TEXT_SIZE  512

    struct msgbuf

    {

        long mtype ;

        int  status ;

        char time[20] ;

        char mtext[TEXT_SIZE] ;

    }  ;

    int main(int argc, char **argv)

    {

        int msqid ;

        struct msqid_ds info ;

        struct msgbuf buf1 ;

        int flag ;

        int  recvlength ;

        int key ;

        int mtype ;

        key = ftok("msg.tmp", 0x01 ) ;

        if ( key < 0 )

        {

            perror("ftok key error") ;

            return -1 ;

        }

        msqid = msgget( key, 0 ) ;

        if ( msqid < 0 )

        {

            perror("get ipc_id error") ;

            return -1 ;

        }

        recvlength = sizeof(struct msgbuf) - sizeof(long) ;

        memset(&buf1, 0x00, sizeof(struct msgbuf)) ;

        mtype = 1 ;

        flag = msgrcv( msqid, &buf1, recvlength ,mtype,0 ) ;

        if ( flag < 0 )

        {

            perror("recv message error ") ;

            return -1 ;

        }

        printf("type=%d,time=%s, message=%s ", buf1.mtype, buf1.time,  buf1.mtext) ;

        system("ipcs -q") ;

       return 0 ;

    }

    (3)编译与执行程序

    ①    在当前目录下利用>msg.tmp建立空文件msg.tmp。

    ②    编译发送消息队列程序 gcc msgsnd.c -o  msgsnd。

    ③    执行./msgsnd,执行结果如下:

      ----- Message Queues --------

    key        msqid      owner      perms      used-bytes   messages   

    0x0101436d 294912     zjkf       600        1072         2          

    ④    编译接收消息程序 gcc msgrcv.c -o msgrcv

    ⑤    执行./msgrcv,执行结果如下:

     type=1,time=03:23:16, message=happy new year!

    ------ Message Queues --------

    key        msqid      owner      perms      used-bytes   messages   

    0x0101436d 294912     zjkf       600        536          1         

    ⑥    利用ipcrm -q 294912删除该消息队列。因为消息队列是随内核持续存在的,在程序中若不利用msgctl函数或在命令行用ipcrm命令显式地删除,该消息队列就一直存在于系统中。另外信号量和共享内存也是随内核持续存在的。

    摘录自《深入浅出Linux工具与编程》

  • 相关阅读:
    链表总结
    源码,反码,补码,位运算
    JAVA打印乘法口诀表
    JAVA打印空三角形
    JAVA打印三角形
    列表,元组,字典,集合类型
    for 循环 ,数字类型,以及字符串类型
    基本运算符补充,流程控制if判断与while循环
    内存管理,数据类型的基本使用与基本运算符(python2中与用户交互)
    编程的分类,以及运行python解释器的原理,最后变量
  • 原文地址:https://www.cnblogs.com/sdushmily/p/10118110.html
Copyright © 2011-2022 走看看