消息队列可以认为是一个消息链表,System V 消息队列使用消息队列标识符标识。具有足

够特权的任何进程都可以往一个队列放置一个消息,具有足够特权的任何进程都可以从一个给定队列读出一个消息。在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达。System V 消息队列是随内核持续的,只有在内核重起或者显示删除一个消息队列时,该消息队列才会真正被删除。可以将内核中的某个特定的消息队列画为一个消息链表,如下图所示:

对于系统中每个消息队列,内核维护一个msqid_ds的信息结构:

struct msqid_ds

{

struct msqid_ds {

struct ipc_perm msg_perm;

struct msg *msg_first; /* first message on queue,unused */

struct msg *msg_last; /* last message in queue,unused */

__kernel_time_t msg_stime; /* last msgsnd time */

__kernel_time_t msg_rtime; /* last msgrcv time */

__kernel_time_t msg_ctime; /* last change time */

unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */

unsigned long msg_lqbytes; /* ditto */

unsigned short msg_cbytes; /* current number of bytes on queue */

unsigned short msg_qnum; /* number of messages in queue */

unsigned short msg_qbytes; /* max number of bytes on queue */

__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */

__kernel_ipc_pid_t msg_lrpid; /* last receive pid */

};

System V 消息队列操作函数

系统V消息队列API共有四个,使用时需要包括几个头文件:

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

)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字节,则把该消息截断,截断部分将丢失。

msgrcv手册中详细给出了消息类型取不同值时(>0;
<0; =0),调用将返回消息队列中的哪个消息。

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

  1. 消息队列中有了满足条件的消息;

  2. msqid代表的消息队列被删除;

  3. 调用msgrcv()的进程被信号中断;

调用返回:成功返回读出消息的实际字节数,否则返回-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。

代码如下:

#include
<stdio.h>

#include
<stdlib.h>

#include
<unistd.h>

#include
<sys/ipc.h>

#include
<sys/msg.h>

#include
<sys/types.h>

#define
MSG_R 0400

#define
MSG_W 0200

#define
SVMSG_MODE (MSG_R | MSG_W | MSG_R >>3 | MSG_R >>6)

struct
msgbuf

{

long
mtype;

char
mtext[1];

};

void
system_v_test()

{

int
msqid;

struct
msqid_ds info;

struct
msgbuf buf;

msqid=msgget(IPC_PRIVATE,SVMSG_MODE
| IPC_CREAT);

buf.mtype=1;

buf.mtext[0]=1;

msgsnd(msqid,&buf,1,0);

msgctl(msqid,IPC_STAT,&info);

printf("read-write:%3o,cbytes=%lu,qnum=%lu,qbytes=%lu\n",info.msg_perm.mode
&
0777,(ulong)info.msg_cbytes,(ulong)info.msg_qnum,(ulong)info.msg_qbytes);

msgctl(msqid,IPC_RMID,NULL);

}

运行结果:

linux c编程:System V消息队列一的更多相关文章

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

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

  2. Linux进程间通信——使用System V 消息队列

    消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问 ...

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

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

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

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

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

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

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

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

  7. 第6章 System V消息队列

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

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

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

  9. (转)Linux环境进程间通信----系统 V 消息队列列

    转:http://www.ibm.com/developerworks/cn/linux/l-ipc/part3/ 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.作为早期unix通 ...

随机推荐

  1. 学习使用master.dbo.spt_values表

    如果要生成的临时表中有个连续的数字列,或者连续的日期列,如下所示: 2012-1-1 2012-1-2 2012-1-3 ... ... 可以这样写: declare @begin datetime, ...

  2. postman --发送json请求

    转自: http://blog.csdn.net/wangjun5159/article/details/47781301 简介: postman是一个很好的http模拟器,在测试rest服务时是很好 ...

  3. Python脚本性能剖析

    ################### #Python脚本性能剖析 ################### cProfile/profile/hotshot用于统计Python脚本各部分运行频率和耗费 ...

  4. 阻塞赋值与非阻塞赋值(verilog篇)

    阻塞赋值与非阻塞赋值(verilog篇) 2017-09-30 竹海 相约电子ee 相信刚刚接触verilog的读者,多少对阻塞赋值和非阻塞赋值仍有一些困惑.笔者在这篇文章,带领大家深入的理解这两者的 ...

  5. Python内置函数之bytes()

    该函数是一个类对象: class bytes([source[,encoding[,errors]]]) 返回值为字节对象,当第一个参数为字符串时,必须提供第二个参数,第二个参数为编码类型的字符串. ...

  6. Math函数的"四舍五入",Floor,Ceiling,Round的一些注意事项!

    1.Math.Round:四舍六入五取偶 引用内容 Math.Round(0.0) //0Math.Round(0.1) //0Math.Round(0.2) //0Math.Round(0.3) / ...

  7. 配置LANMP环境(2)-- 安装ifconfig命令与安装SecureCRT

    一.安装ifconfig命令 yum whatprovides ifconfig yum install net-tools 安装这个命令就是为了查看虚拟机的ip地址,SecureCRT连接必须要ip ...

  8. mysql的binlog和slow_log慢日志

    redo undo 锁 ----------------------------------------- 日志管理 log-error=/var/log/mysql.log 二进制日志的“总闸” 作 ...

  9. Xcode调试项目时取消弹出框提示授权

    问题2: instruments wants permission to analyze other processes.'DTServiceHub'需要控制另外一个进程,以便继续调试,键入密码以允许 ...

  10. Win10系统如何配置Tomcat环境变量

    我们知道win10用户在配置Tomcat环境变量的时候,首先需要配置JAVA,这样才能配置Tomcat环境.很多用户并不知道要如何进行配置,下面就给大家介绍win10系统怎样Tomcat环境变量的. ...