消息队列可以认为是一个消息链表,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. 将 ASP.NET Core 2.0 项目升级至 ASP.NET Core 2.1

    主要升级步骤如下: 将 .csproj 项目文件中的 target framework 改为 netcoreapp2.1 <TargetFramework>netcoreapp2.1< ...

  2. 如何下载PDF?

    IIS MIME类型配置: application/octet-stream

  3. nodejs 命令行交互

    人机交互 function readSyncByfs(tips) { tips = tips || '> '; process.stdout.write(tips); process.stdin ...

  4. 如何修改两个PHP版本,php-v和phpinfo两个不同的版本

    先查找php.ini find / -name php.ini得出两个ini/usr/local/php/etc/php.ini/etc/php.ini php -i | grep php.ini查看 ...

  5. unity, 自定义类中使用print

    在unity脚本中自定义c#类,而且不继承MonoBehaviour的话,若还想在其中使用print函数,可以用MonoBehaviour.print(...).

  6. Eclipse RCP应用开发(概念)

    学习Eclipse RCP应用开发,对其中一些相关的概念需要了解. 让我们在讲解概念前先思考两个问题. 问题一.什么是Eclipse 大部分同学会回答eclipse是IBM公司开发的java集成开发环 ...

  7. python C PyObject

    #include"Python.h" //three ways : /* PyObject *MyFunction(PyObject *self, PyObject *args); ...

  8. Modification of UCT with Patterns in Monte-Carlo Go(论文阅读)

    摘要:用于解决多臂赌博机UCB1算法已经被扩展成了解决极大极小树搜索的UCT算法.我们开发了一套Monte-Carlo围棋程序,MoGo,这是第一个使用UCT算法实现的计算机围棋程序.我们解释了为了围 ...

  9. LeetCode455. Assign Cookies

    Description Assume you are an awesome parent and want to give your children some cookies. But, you s ...

  10. android中通过代码来设置蓝牙永久可见性

    废话不多说,直接阐述: 前段时间在搞一个android项目,其中有一个功能要求需要蓝牙可见性永久打开,但是开发过android蓝牙的程序员应该都知道,goole提供的api中没有设置蓝牙永久可见性的接 ...