Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6890
  • 博文数量: 10
  • 博客积分: 105
  • 博客等级: 民兵
  • 技术积分: 80
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-09 23:01
文章分类

全部博文(10)

文章存档

2013年(10)

我的朋友

分类: 嵌入式

2013-01-11 21:47:35

一、Linux采用消息队列的方式来实现消息传递。这种消息的发送方式是:发送方不必等待接收方检查它所收到的消息就可以继续工作下去,而接收方如果没有收到消息也不需等待。

IPC标识符:每一个I P C目标都有一个唯一的I P C标识符。这里所指的I P C目标是指一个单独的消息队列、一个信号量集或者一个共享的内存段。系统内核使用此标识符在系统内核中指明 I P C目标。

IPC 关键字:想要获得唯一的标识符,则必须使用一个 I P C关键字。客户端进程和服务器端进程必须双方都同意此关键字。这是建立一个客户机/服务器框架的第一步。在System V IPC机制中,建立两端联系的路由方法是和I P C关键字直接相关的。通过在应用程序中设置关键字值,每一次使用的关键字都可以是相同的。一般情况下,可以使用f t o k ( )函数为客户端和服务器端产生关键字值。

二、ipcs 命令

命令ipcs用于读取System V IPC目标的状态。
ipcs -q: 只显示消息队列。
ipcs -s: 只显示信号量。
ipcs -m: 只显示共享内存。
ipcs –help: 其他的参数


1)int msgget(key_t key, int msgflg)

参数key是一个键值,由ftok获得;msgflg参数是一些标志位。该调用返回与健值key相对应的消息队列描述字。

在以下两种情况下,该调用将创建一个新的消息队列:

  • 如果没有消息队列与健值key相对应,并且msgflg中包含了IPC_CREAT标志位;
  • key参数为IPC_PRIVATE;

  • 参数msgflg可以为以下:IPC_CREAT、IPC_EXCL、IPC_NOWAIT或三者的或结果。
  • 调用返回:成功返回消息队列描述字,否则返回-1。

    注:参数key设置成常数IPC_PRIVATE并不意味着其他进程不能访问该消息队列,只意味着即将创建新的消息队列。



    2)int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);
    该系统调用从msgid代表的消息队列中读取一个消息,并把消息存储在msgp指向的msgbuf结构中。

    msqid为消息队列描述字;消息返回后存储在msgp指向的地址,msgsz指定msgbuf的mtext成员的长度(即消息内容的长度),msgtyp为请求读取的消息类型;读消息标志msgflg可以为以下几个常值的或:

    • IPC_NOWAIT 如果没有满足条件的消息,调用立即返回,此时,errno=ENOMSG
    • IPC_EXCEPT 与msgtyp>0配合使用,返回队列中第一个类型不为msgtyp的消息
    • IPC_NOERROR 如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将丢失。
    • 调用返回:成功返回读出消息的实际字节数,否则返回-1。


    3)int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
    向msgid代表的消息队列发送一个消息,即将发送的消息存储在msgp指向的msgbuf结构中,消息的大小由msgze指定。

    对发送消息来说,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待。造成msgsnd()等待的条件有两种:

    • 当前消息的大小与当前消息队列中的字节数之和超过了消息队列的总容量;
    • 当前消息队列的消息数(单位"个")不小于消息队列的总容量(单位"字节数"),此时,虽然消息队列中的消息数目很多,但基本上都只有一个字节。


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

    1. 不满足上述两个条件,即消息队列中有容纳该消息的空间;
    2. msqid代表的消息队列被删除;
    3. 调用msgsnd()的进程被信号中断;


    调用返回:成功返回0,否则返回-1。

    4)int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    该系统调用对由msqid标识的消息队列执行cmd操作,共有三种cmd操作:IPC_STAT、IPC_SET 、IPC_RMID。

    1. IPC_STAT:该命令用来获取消息队列信息,返回的信息存贮在buf指向的msqid结构中;
    2. IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf指向的msqid结构中;可设置属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,同时,也影响msg_ctime成员。
    3. IPC_RMID:删除msqid标识的消息队列;


    调用返回:成功返回0,否则返回-1。


    ----------------------------------------------------------------------------------------------------------------------

    /*msgserver.c*/

    #include
    #include
    #include
    #include
    #include
    #include
    #include

    #define   MSG_FILE "msgserver.c" 
    #define   BUFFER 255 
    #define   PERM S_IRUSR|S_IWUSR 
    /* 服务端创建的消息队列最后没有删除,我们要使用ipcrm命令来删除的 */
    /* ipcrm -q */

    struct msgtype { 
        long mtype; 
        char buffer[BUFFER+1]; 
    };

    int main() 

        struct msgtype msg; 
        key_t key; 
        int msgid; 
        
        if((key=ftok(MSG_FILE,'a'))==-1) 
        { 
            fprintf(stderr,"Creat Key Error:%s\n", strerror(errno)); 
            exit(1); 
        }

        if((msgid=msgget(key, PERM|IPC_CREAT|IPC_EXCL))==-1) 
        {
            fprintf(stderr, "Creat Message Error:%s\n", strerror(errno)); 
            exit(1);
        } 
        printf("msqid = %d\n", msgid);
        while(1)
        { 
            msgrcv(msgid, &msg, sizeof(struct msgtype), 1, 0); 
            fprintf(stderr,"Server Receive:%s\n", msg.buffer); 
            msg.mtype = 2; 
            msgsnd(msgid, &msg, sizeof(struct msgtype), 0); 
        } 
        exit(0); 

    /* msgclient.c */

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    #define   MSG_FILE "msgserver.c" 
    #define   BUFFER 255 
    #define   PERM S_IRUSR|S_IWUSR

    struct msgtype { 
        long mtype; 
        char buffer[BUFFER+1]; 
    };

    int main(int argc, char **argv) 

        struct msgtype msg; 
        key_t key; 
        int msgid; 
        
        if(argc != 2) 
        { 
            fprintf(stderr,"Usage:%s string\n", argv[0]); 
            exit(1); 
        } 
        
        if((key=ftok(MSG_FILE,'a'))==-1) 
        { 
            fprintf(stderr,"Creat Key Error:%s\n", strerror(errno)); 
            exit(1); 
        } 
        
        if((msgid=msgget(key, PERM))==-1) 
        { 
            fprintf(stderr,"Creat Message  Error:%s\n", strerror(errno)); 
            exit(1); 
        } 
        
        msg.mtype = 1; 
        strncpy(msg.buffer, argv[1], BUFFER); 
        msgsnd(msgid, &msg, sizeof(struct msgtype), 0);  
        memset(&msg, '\0', sizeof(struct msgtype)); 
        msgrcv(msgid, &msg, sizeof(struct msgtype), 2, 0); 
        fprintf(stderr, "Client receive:%s\n", msg.buffer); 
        exit(0);
    }  


阅读(291) | 评论(0) | 转发(0) |
0

上一篇:共享内存

下一篇:linux信号量

给主人留下些什么吧!~~