6.1 概述

  System V消息队列在内核中是list存放的,头结点中有2个指针msg_first 和msg_last。其中每个节点包含:下个节点地址的指针、类型、长度、数据等。

6.2 函数

6.2.1 msgget 函数

功能:msgget 函数用于创建一个新的消息队列或访问一个已存在的消息队列。 
头文件 #include <sys/msg.h>
函数原型 int msgget(key_t key, int oflsg);
返回值 成功返回非负的标识符,失败返回-1.
说明 1.返回值是一个非负标识符,其它三个msg函数用它来指代队列;它是基于key值产生的,而key可以是ftok的返回值,也可以是常数IPC_PRIVATE
  2.oflag:读写权限的组合(0666) | IPC_CREAT | IPC_EXCL

6.2.2 msgsnd 函数

功能:往消息队列中写入一个消息
头文件 #include <sys/msg.h>
函数原型 int msgsnd(int msqid, const void *ptr, size_t length, int flag);
返回值 成功返回0,失败返回-1
说明 1.msqid是msgget返回的标识符
 

2.ptr参数是一个结构体指针,且第一个成员是long型,模板如下,也可自定义。

struct msgbuf {
  long mtype;  /* message type, must be > 0 */
  char mtext[1];  /* message data */
};

  3.flag参数即可以是0,是阻塞函数,如果无法存放消息(消息队列中有太多的消息或者字节数),就休眠
  4.flag参数可以是IPC_NOWAIT,变成非阻塞的。如果无法存放消息,就返回-个EAGAIN错误。

6.2.3 msgrcv 函数

功能:从消息队列中读出一个消息
头文件 #include <sys/msg.h>
函数原型 ssize_t msgrcv(int msqid, void *ptr, size_t length, long type, int flag);
返回值 成功返回读出的字节数,失败返回-1.
 说明 1.msqid是msgget返回的标识符。 
  2.ptr是接受消息的结构体,和msgsnd一样,包含long类型
  3.length指结构体中数据部分的大小,是该函数能返回的最大数量,不包含long型字段。
 

4.type:从消息队列中指定读出什么样的消息。

如果 type = 0,返回第一个消息;

如果 type > 0,返回其类型的第一个消息;

如果 type < 0,返回小于或等于type参数绝对值的消息中类型值最小的第一个消息。

 

5.flag:0,不做任何处理,没有消息就阻塞;

flag:IPC_NOWAIT,没有消息就返回一个ENOMSG的错误;

flag:MSG_NOERROR,如果接受消息数据部分大于length参数,就返回截短的数据,否则返回E2BIG错误。

6.2.4 msgctl 函数

功能:提供一个消息队列上的各种控制操作。
头文件 #include <sys/msg.h>
函数原型 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
返回值 成功返回0,失败返回-1
说明 IPC_RMID:从系统中删除消息队列。
  IPC_SET:设置msgid_ds结构中的msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_qbytes
  IPC_STAT:返回当前msqid_ds结构

6.3 简单的程序

6.3.1 msgcreate 程序

创建一个消息队列,可以使用-e命令行选项来指定IPC_EXCL标志。

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <sys/msg.h>

 // msgcreate [-e] /tmp/msgqueue
 int main(int argc, char **argv)
 {
     ;
      | IPC_CREAT;
     ;

     )
     {
         switch (c)
         {
             case 'e':
                 oflag |= IPC_EXCL;
                 break;
             default:
                 break;
         }
     }

     )
     {
         printf("usage: msgcreate [-e] <pathname>");
         ;
     }

     // 创建一个System V 消息队列
     mqid = msgget(ftok(argv[optind], ), oflag);
     )
     {
         perror("msgget error");
         ;
     }

     ;
 }

6.3.2 msgsnd 程序

把一个指定长度和类型的消息放到指定的消息队列中。

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <sys/msg.h>

 struct my_msgbuf
 {
     long type;
     ];
 };

 // msgsnd <pathname> <bytes> <type>
 // msgsnd  /tmp/msqueue 100 1
 int main(int argc, char **argv)
 {
      | IPC_CREAT;
     ;
     ;
     ;

     )
     {
         printf("usage: msgsnd <pathname> <bytes> <type>\n");
         ;
     }
     len = atoi(argv[]);
     type = atoi(argv[]);

     // 创建一个System V 消息队列
     mqid = msgget(ftok(argv[], ), oflag);
     )
     {
         perror("msgget error");
         ;
     }

     // 构造数据
     struct my_msgbuf *ptr = (struct my_msgbuf*)malloc(sizeof(struct my_msgbuf) + len);
     memset(ptr, , sizeof(struct my_msgbuf) + len);
     ptr->type = type;

     // 发送消息
     msgsnd(mqid, ptr, len, );

     ;
 }

6.3.3 msgrcv 程序

从消息队列中读出指定的消息,可以使用-n命令行改成非阻塞

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <sys/msg.h>

 struct my_msgbuf
 {
     long type;
     ];
 };

 #define MAX_MSG 100

 // msgrcv [-n] [-t type] <pathname>
 // msgrcv -t 1 /tmp/msqueue
 int main(int argc, char **argv)
 {
     ;
      | IPC_CREAT;
     ;
     ;
     ;
     struct my_msgbuf *buf = (struct my_msgbuf *)malloc(sizeof(struct my_msgbuf) + MAX_MSG);
     memset(buf, , sizeof(struct my_msgbuf) + MAX_MSG);

     )
     {
         switch (c)
         {
             case 'n':
                 flag |= IPC_NOWAIT;
                 break;
             case 't':
                 type = atoi(optarg);
                 break;
             default:
                 break;
         }
     }

     )
     {
         printf("usage: msgrcv [-n] [-t type] <pathname>");
         ;
     }

     // 创建一个System V 消息队列
     mqid = msgget(ftok(argv[optind], ), oflag);
     )
     {
         perror("msgget error");
         ;
     }

     // 读取消息
     int n = msgrcv(mqid, buf, MAX_MSG, type, flag);
     printf("recv n = %d\n", n);

     ;
 }

6.3.4 msgrmid 程序

从系统中删除一个System V消息队列

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <sys/msg.h>

 // msgrmid <pathname>
 // msgrmid /tmp/msqueue
 int main(int argc, char **argv)
 {
     ;

     )
     {
         printf("usage: msgrmid <pathname>\n");
         ;
     }

     // 创建一个System V 消息队列
     mqid = msgget(ftok(argv[], ), );
     )
     {
         perror("msgget error");
         ;
     }

     // 删除一个System V 消息队列
     msgctl(mqid, IPC_RMID, NULL);

     ;
 }

第6章 System V消息队列的更多相关文章

  1. 第二十五章 system v消息队列(一)

    IPC对象的持续性 随进程持续 :一直存在直到打开的最后一个进程结束.(如pipe和FIFO) 随内核持续 :一直存在直到内核自举(内核自举就是把主引导记录加载到内存,并跳转执行这段内存)或显示删除( ...

  2. 第二十七章 system v消息队列(三)

    消息队列实现回射客户/服务器 msg_srv.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> ...

  3. 第二十六章 system v消息队列(二)

    msgsnd int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 作用: 把一条消息添加到消息队列中 参数: msqi ...

  4. 进程间通信 System V 消息队列

    1.msgget (key_t ket,int flag) ; //创建一个新的消息队列或者访问一个已存在的消息队列 2.msgsnd(int msid, const void *ptr ,size_ ...

  5. Linux进程通信之System V消息队列

    System V消息队列是Open Group定义的XSI,不属于POSIX标准.System V IPC的历史相对很早,在上个世70年代后期有贝尔实验室的分支机构开发,80年代加入System V的 ...

  6. 利用System V消息队列实现回射客户/服务器

    一.介绍 在学习UNIX网络编程 卷1时,我们当时可以利用Socket套接字来实现回射客户/服务器程序,但是Socket编程是存在一些不足的,例如: 1. 服务器必须启动之时,客户端才能连上服务端,并 ...

  7. UNIX环境高级编程——system V消息队列

    unix早期通信机制中的信号能够传送的信息量有限,管道则只能传送无格式字节流,这远远是不够的.     消息队列(也叫报文队列)客服了这些缺点:     消息队列就是一个消息的链表.     可以把消 ...

  8. linux c编程:System V消息队列一

    消息队列可以认为是一个消息链表,System V 消息队列使用消息队列标识符标识.具有足 够特权的任何进程都可以往一个队列放置一个消息,具有足够特权的任何进程都可以从一个给定队列读出一个消息.在某个进 ...

  9. linux网络编程之system v消息队列(二)

    今天继续学习system v消息队列,主要是学习两个函数的使用,开始进入正题: 下面则开始用代码来使用一下该发送函数: 在运行之前,先查看一下1234消息队列是否已经创建: 用上次编写的查看消息队列状 ...

随机推荐

  1. Nginx反向代理讲解和配置

    首先来介绍下Nginx的反向代理.代理服务器一般分为正向代理(通常直接称为代理服务器)和反向代理. 画个图我们就好理解了. 正向代理:可以想象成是路由器,我们要通过它来上网的那种.(可以说是客户端的代 ...

  2. Oracle数据库——索引、视图、序列和同义词的创建

    一.涉及内容 1.理解索引的概念和类型. 2.掌握创建索引的命令. 3.理解视图的概念和优点. 4.理解可更新视图应具备的特点. 5.掌握创建一般视图和可更新视图的命令. 6.理解序列和同义词的概念和 ...

  3. pythonchallenge关卡破解

    第一关:pow(2,38) 第二关: import string table = str.maketrans(string.ascii_lowercase, string.ascii_lowercas ...

  4. CentOS 6.4下PXE+Kickstart无人值守安装操作系统 转

    一.简介 1.1 什么是PXE PXE(Pre-boot Execution Environment,预启动执行环境)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持 ...

  5. 【转】.NET多种WebKit内核/Blink内核浏览器初步测评报告

    第1篇:.NET多种WebKit内核/Blink内核浏览器初步测评报告 本文转自“吾乐吧软件站”,原文链接:http://www.wuleba.com/?p=23590 报告研究时间:2013-10- ...

  6. 【转】Deprecated: Function ereg_replace() is deprecated的解决方法

    这个问题是因为你用的php版本过高. 在php5.3中,正则函数ereg_replace已经废弃,而dedecms还继续用.有两个方案可以解决以上问题: 1.把php版本换到v5.3下. 2.继续使用 ...

  7. C#的浅拷贝和深拷贝

    C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量 对于值类型变量,深拷贝和前拷贝都是通过赋值操作符号(=)实现,其效果一致,将对象中的值类型的字段拷贝到新的对象中.这个很容易理解. 本文重 ...

  8. BI案例:某通信企业综合报表和决策分析系统实施案例

    业务需求 某家位列国内五大电信运营商之列的通信公司(以下简称“通信公司”)在多年的运营过程中,积累了大量的业务数据,分散在各个运营系统中(计费系统.九七工程.网管系统等).这些系统主要是面向公司的日常 ...

  9. Hive(四):c#通过odbc访问hive

    hive odbc 驱动配置成功后,通过c#访问就变得比较简单了,分为查询与更新操作,直接附上测试代码.在此过程中需要注意c#工程编译的目标平台 读写访问代码示例: public class Hive ...

  10. jQuery checkbox相关

     搬家来的~~~ $('#checkbox').attr('checked'); 返回的是checked或者是undefined解决办法 分类: Jquery2014-03-18 17:10 5523 ...