linux 进程学习笔记-消息队列messagequeue
可以想象,如果两个进程都可以访问同一个队列:其中一个进程(sender)向其中写入结构化数据,另外一个进程(receiver)再从其中把结构化的数据读取出来。那么这两个进程就是在利用这个队列进行通信了,这个队列也就称为消息队列(message queue)。 消息队列有system V和POSIX两种,这里说system V的。 内核维护中很多个消息队列(因为有很多不同的进程要用它们来通信,不可能共享一个),我们使用一个key_t类型的key来让发送端和接收端进程都清楚了解自己使用的是哪个消息队列。 key_t类型实际上就是一个int类型 typedef int __kernel_key_t; (查看这里) typedef __kernel_key_t key_t; (查看这里) 所以我们可以简单地想象成每个消息队列都有一个自己的唯一id。虽然直接为两个进程指定一个常数值(比如12345)作为你创建的消息队列的key一般是没有问题的,但为了保证唯一性和可读性,我们可以用ftok()函数来创建该key。 key_t ftok(const char *path, int id); 第一个参数是你指定的文件(或目录)路径,id是一个子序号,该函数将指定的文件路径对应的索引节点号和id结合起来生成一个key值,比如指定文件的索引节点号为56672,换算成16进制为0xDD60,而你指定的id值为52,换算成16进制为0x34,则最后的key_t返回值为0x3400DD60。 我们可以通过msgget函数来创建一个新的消息队列或者取得已经存在的消息队列。 int msgget(key_t key, int msgflg); key参数: 就是要新建或获取的消息队列的唯一标识,其一般是由上面的ftok函数成长的,但有一个例外是其还可以是一个叫做IPC_PRIVATE的值(实际上是值为0的key): #define IPC_PRIVATE ((__kernel_key_t) 0) 当key为IPC_PRIVATE时,则msgget始终创建一个新的消息队列。 msgflg参数: 其有两层含义,一是该参数可以取值IPC_CREATE,表示请求msget函数新建消息队列;也可以是 IPC_CREATE|IPC_EXCL的按位组合,表示请求新建消息队列但如果队列已经存在的话则报错。二是该参数表示权限控制,比如666表示全部可读写。那么如果该参数写成IPC_CREATE|IPC_EXCL|666则表示请求新建消息队列但如果队列已经存在的话则报错并且权限为666 与管道不一样,我们向消息队列中写入会从其中读取信息时采用的不是字节流而是按照某一约定的结构体,比如: struct msg { long msg_type; char msg_txt[SIZE]; }; 其第一个字段是一个长整形数,表示该信息的类型,这个字段可以让我们将不同“类型”的消息写入同一个管道,比如可以用1表示普通信息,用2表示错误信息。当读取端从消息队列中读取消息时,如果不指定类型(类型值为0)则其读取队列中的第一个消息,而如果指定了类型的话,则读取该类型的第一个消息(所以其并不完全地按照先入先出的顺序) 后面的字段表示消息的内容部分,一般用一个字节数组,但其实是可以自定义的,比如: struct msg { long msg_type; int other_filed; char msg_txt[SIZE]; }; 用msgsnd函数来发送消息到消息队列中去: int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) msgid参数: 消息队列的id,也就是上面所说的key. msgp参数: 指向消息结构体的指针 msgsz参数: 表示消息结构体的大小,由于消息结构体是可以自定义的,所以必须指定大小类分割连续的消息 msgflg参数: 这个参数主要用于如下情况:消息队列中的消息数目达到了系统上限 或 消息队列没有足够的空间来容纳消息字节。此时,如果指定了msgflg为IPC_NOWAIT的话(msgflg & IPC_NOWAIT != ),那么消息将不被发送,而函数直接返回。相反的(msgflg & IPC_NOWAIT == ),调用该函数的进程将会被挂起,直到下面三种情况之一发生: )上述两种情况不再满足,消息被发送 )消息队列被系统移除,消息不被发送。 )进程接收到信号转入进行信号处理,这种情况下,消息不会被发送。 struct message {
long msg_type;
char msg_text[SIZE];
} msg;
…
msg.msg_type = ;
strcpy(msg.msg_text, "This is message 1");
...
result = msgsnd(msqid, (void *) &msg, sizeof(msg.msg_text), IPC_NOWAIT); 相对应的,msgrcv函数用来从消息队列中读取消息: ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); msgtyp参数: 如果该值为0,则读取消息队列中的第一个消息 如果该值大于0,则读取消息队列中具有指定类型的第一个消息 如果该值小于0,则读取消息队列中类型值小于或等于指定值的绝对值的最小类型值的第一个消息(好晕,the first message of the lowest type that is less than or equal to the absolute value of msgtyp) msgflg参数: 这个参数主要用于消息队列中当没有消息(或指定类型的消息)可供读取时,如果指定了msgflg为IPC_NOWAIT的话(msgflg & IPC_NOWAIT != ),函数将直接返回而放弃读取。相反的(msgflg & IPC_NOWAIT == ),调用该函数的进程将会被挂起,直到下面三种情况之一发生: )有消息到来,可读取了 )消息队列被系统移除,放弃消息读取 )进程接收到信号转入进行信号处理,放弃消息读取 msgflg也可以指定如下操作: /* msgrcv options */ #define MSG_NOERROR 010000 /* no error if message is too big */ #define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/ 另外还有一个msgctl函数可以对消息队列进行一些其他控制和读取消息队列的属性消息,不过在这之前需要先了解下消息队列本身的数据结构msqid_ds: struct msqid_ds {
struct ipc_perm msg_perm;
struct msg *msg_first; /* first message in 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 */
};
其中msg_perm字段表示消息队列的所有者和权限信息:
struct ipc_perm
{
__kernel_key_t key;
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
__kernel_mode_t mode;
unsigned short seq;
}; msg_qbytes表示消息队列所能容纳的最大消息字节数。 再来看看msgctl函数: int msgctl(int msqid, int cmd, struct msqid_ds *buf); cmd参数: 表示要对消息队列执行的操作,可以有如下三种: )IPC_STAT获取消息队列属性信息,并将这些信息放置到第3个参数所设置的buffer中 )IPC_SET 根据buffer中的数据设置消息队列的一些属性,并非所有属性都可设置,其仅仅限于:msg_perm.uid,msg_perm.gid,msg_perm.mode,msg_qbytes 这几种 )IPC_RMID 删除消息队列。 注:IPC_SET和IPC_RMID都会进行相应的权限检查,只有具备权限的进程才能执行相关操作
linux 进程学习笔记-消息队列messagequeue的更多相关文章
- linux进程学习笔记
学习了linux下的进程,觉得应该整理一下,忘得差不多了,顺便回顾一下. 学而时习之,不亦说乎~~ 进程笔记 ,什么是进程? The Single UNIX Specification, Versio ...
- linux进程通信:消息队列
消息队列可以实现两个没有关系的进程之间的通信. 创建了一个消息队列后,进程可以往里面放消息,也可以取消息.因为这个消息队列是有名字的,所以就算是两个没有关系的进程,也能通信. 而且人性化的一点是,可以 ...
- linux 进程学习笔记-进程pipe管道
所谓“进程间通信(IPC,inter-process communication)”,按照其目的讲就是让进程之间能够“共享数据”,“传输数据”,“事件通知”等,我所知道的一共有“管道” “信号” “消 ...
- linux 进程学习笔记-共享内存
如果能划定一块物理内存,让多个进程都能将该内存映射到其自身虚拟内存空间的话,那么进程可以通过向这块内存空间读写数据而达到通信的目的.另外,和消息队列不同的是,共享的内存在用户空间而不是核空间,那么就不 ...
- linux 进程学习笔记-进程状态
task_struct的state字段记录的进程的状态,可分为如下几种: #define TASK_RUNNING 0 可运行状态.这是 “进程正在被CPU运行” 和 “进程正在可运行队列中等待被CP ...
- linux 进程学习笔记-进程调度
在分时系统中,系统将CPU时间划分成无数个时间片(quantum)分配给不同的进程,一个时间片只执行一个进程,并且不停地切换,以让用户感觉到各个进程是在“同时运行”,这中间所需要的策略和算法便是进程调 ...
- linux 进程学习笔记-进程信号sigal
信号(或软中断)是在软件层次上对中断的一个模拟,其运行在“用户空间”,一个进程对另外一个或几个进程通过发送信号来实现异步通信.当接收进程接收到信号后,其可以注册一下处理函数来说对这些信号进行处理(也可 ...
- Linux 进程学习笔记
1.什么是程序?什么是进程?它们有什么区别? 定义: 程序:程序(Program)是一个静态的命令集合,程序一般放在磁盘中,然后通过用户的执行来触发.触发后程序会加载到内存中成为一个个体,就是进程. ...
- linux 进程学习笔记-进程ID,PID
PID,进程号 , 范围在2~(??为什么需要这么多),而一个名为idle (或swapper)的进程占据的编号0,init进程占据了编号1. 进程0和进程1 : 系统启动时会从无到有地创建进程0,它 ...
随机推荐
- Linux是怎么启动的(整理)
昨天笔试考了一道关于linux系统启动的过程,当时没答上来,现在整理出来(其实并不复杂). 按下电源按钮的直到欢迎页出来之后,linux总共做的事可以分为五步来完成. 1. BIOS加电自检: 加电 ...
- typedef 与 define 的区别
1.区别 (1)定义.执行时间.作用域 定义.执行时间: #define pchar char * typedef char *pchar; 定义的格式差别,显而易见的,要注意,define 是不能存 ...
- 如何用openssl命令行生成证书
老大要我在web server里面加上https功能,可是但就使用openssl生成证书就耗费了我两天时间,网上有很多相关的资料,但是都写的很复杂, 照着他们的来,还是走了很多弯路. 我总结一下,步骤 ...
- phpstorm 设置
phpstorm 设置多项目并存 phpstorm 或 webstorm 设置多个项目可以并存: File -> settings -> Directories -> Add Co ...
- 一起学Django之Day01
创建项目 SimilarFacedeMacBook-Pro:PycharmProjects similarface$ django-admin startproject StudyDjango 创建A ...
- MVC中的 @helper
ASP.NET MVC 3支持一项名为“Razor”的新视图引擎选项(除了继续支持/加强现有的.aspx视图引擎外).当编写一个视图模板时,Razor将所需的字符和击键数减少到最小,并保证一个快速.通 ...
- Color.js 方便修改颜色值
这并不是npm上比较活跃的clolr包的中文文档,不过它在最后提到了: The API was inspired by color-js. Manipulation functions by CSS ...
- Windows下安装Oracle 11g全过程。
1. 解压Oracle11.1.0.6 for win32,然后点击setup 2.选择高级安装,下一步 3.选择企业版,下一步 4.修改Oracle基目录,也可以是默认,下一步 5.将状态复选框打上 ...
- Python中的注解“@” 、Java 注解
https://blog.csdn.net/u013474436/article/details/75675113 https://blog.csdn.net/briblue/article/deta ...
- C# WinForm退出方法
1.this.Close(); 只是关闭当前窗口,若不是主窗体的话,是无法退出程序的,另外若有托管线程(非主线程),也无法干净地退出: 2.Application.Exit(); 强制所有消息中 ...