博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux进程IPC浅析[进程间通信SystemV消息队列]
阅读量:3746 次
发布时间:2019-05-22

本文共 5390 字,大约阅读时间需要 17 分钟。

Linux进程IPC浅析[进程间通信SystemV消息队列]

  1. System V IPC的概述
  2. System V IPC对象访问
  3. System V IPC消息队列

System V IPC的概述

System V Ipc概述:

1:Unix系统存在信号,管道和命名管道等基本通信机制
2:System V引入三种高级进程间通信机制

消息队列,共享内存和信号量

IPC对象存在于内核中而不是文件系统中,由用户控制释放,不像管道的释放由内核控制

3:IPC对象用过其标识符来引用和访问,所有IPC对象在内核空间中有唯一性表示ID,在用户空间中的唯一标识为key
Linux IPC继承来自System V Ipc

System V IPC对象访问

IPC对象是全部对象

可用ipcs,ipcrm等命令查看或删除
这里写图片描述
从上面我们可以看到共享内存端.信号量数组和消息队列

每个IPC对象的都由get函数创建

msgget,shmget,semget调用get函数时必须制定关键字key

IPC对象的权限和所有者结构体:struct ipc_perm{    uid_t uid;    gid_t gid;    uid_t cuid;    gid_t cgid;    mode_t mode;//权限    ......;}

System V IPC消息队列

消息队列概述:

1:消息队列是内核中的一个链表

2:用户进程将数据传输到内核后,内核重新添加一些如用户ID,组ID,读写进程的ID和优先级等相关信息后并打成一个数据包成为消息
3:允许一个或者多个进程往消息队列中写消息和读消息,但一个消息只能被一个进程读取,读取完毕后就自动删除
4:消息队列具有一定的FIFO特性,消息可以按照顺序发送到队列中,也可以几种不同的方式从队列中读取,每个消息队列在内核中用一个唯一的IPC标识ID表示
5:消息队列的实现包括创建和打开消息队列,发送消息,读取消息,和控制消息队列四种操作

消息队列属性:

消息队列的属性:struct msgid_ds{    struct ipc_perm msg_perm;//IPC对象的权限和所有者结构体    msgqnum_t msg_qnum; //队列中的消息个数    msglen_t msg_qbytes; //队列中最大的字节数    pid_t msg_lspid; //最后一个消息发送者的pid    pid_t msg_lrpid; //最后一个消息接受者的pid    time_t msg_stime; //最后发送的时间    time_t msg_ctime; //消息队列最后改变的时间    ......}

消息队列函数:

打开或者创建消息队列

#include
int msgget(key_t key,int flag);返回:成功返回内核中消息队列的表示ID,出错返回-1(不存在则创建,存在则打开)参数: key:用户指定的消息队列健值 flag:IPC_CREAT,IPC_EXCL等权限组合(IPC_CREATE | IPC_EXCL |0777) 注意:若创建消息队列,key可制定健值,也可将之设置为 IPC_PRIVATE.若打开进行查询,则key不能为0必须是一个非0的值否则查询不到;

消息队列的控制函数:

#include
int msgctl(int msgid,int cmd,struct msqid_ds *buf);返回:成功返回0,出错返回-1参数: msgid:消息队列ID buf:消息队列属性指针 cmd(有很多): IPC_STAT获取消息队列的属性,取此队列的msqid_ds结构,并将其存放在buf指向的结构中去 IPC_SET:设置属性,按有buf指向的结构中的值,设置与此队列相关的结构中的字段 IPC_RMID:删除队列,从系统中删除该消息队列以及仍在该队列上的所有数据

消息队列的发送函数:

消息队列的发送:#include
int msgsnd(int msgqid,const void *ptr,size_t nbytes,int flag);返回:成功返回0,出错返回-1-------------参数ptr:struct mymesg{ long mtype; //消息类型 char mtext[512] //消息数据的本身} mtype指的是消息的类型,它由一个证书来代表,并且它只能是大于0的整数mtext是消息数据的本身(文本或者二进制类型都可以)在Linux中,消息的最大长度是4056个字节,其中包括mtype,它占有4个字节结构体mymesg用户可自定义,但是第一个成员必须是mtype-------------参数nbytes: 指定消息的大小,不包括mtype的大小,也就是仅仅只是消息本身的大小(sizeof(struct mymesg) - sizeof(long))参数flag: 0:阻塞 IPC_NOWAIT:类似与文件I/O的非阻塞状态 若消息队列已经满了(或者是队列中的消息总数等于系统限制值,或队列中的字节总数等于系统限制值): 指定IPC_NOWAIT 使得msgsnd立即出错返回EAGAIN, 如果指定0,则进程 阻塞直到有空间可以容纳要发送的消息 或从系统中删除了此队列 或捕捉到一个信号,并且从信号处理程序返回

消息队列的接受

#include
ssize_t msgrcv(int msgqid,void *ptr,size_t nbytes,long type,int flag);返回:成功返回消息的数据部分长度,出错返回-1参数: msgqid:消息队列ID ptr:指向存放消息的缓存 nbytes:消息缓存的大小,不包括mtype的大小,计算方式:nbytes = sizeof(struct mymesg) - sizeof(long)如果大小不对,那么可能不能获取完整的消息; type:消息类型 type==0 :获得消息队列中的第一个消息 type>0:获得消息队列中类型为type的第一个消息 type<0:获得消息队列中小于或等于type绝对值的消息 flag:0或者IPC_NOWAIT

直接上代码,msg_send

/* * =========================================================================== * *       Filename:  msg_send.c *    Description:  消息的发送 *        Version:  1.0 *        Created:  2017年04月10日 21时54分13秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include
#include
#include
#include
#define BUFFER 1024typedef struct{ long type; char content[BUFFER];}MSG;int main(int argc,char * argv[]){ if(argc < 2){ printf("缺少参数"); exit(EXIT_FAILURE); } //传入的字符串转换为整形 key_t key = atoi(argv[1]); printf("key:%d\n",key); int msg_id; //第一次是创建,第二次是获取 if((msg_id = msgget(key,IPC_CREAT|IPC_EXCL|0777)) < 0){ printf("msg error\n"); } MSG msg1 = {
1,"hello"}; MSG msg2 = {
2,"world"}; MSG msg3 = {
5,"nihao"}; MSG msg4 = {
7,"woshizzf"}; if(msgsnd(msg_id,&msg1,sizeof(MSG)-sizeof(long),IPC_NOWAIT) != 0){ printf("send msg1 error\n"); } if(msgsnd(msg_id,&msg2,sizeof(MSG)-sizeof(long),IPC_NOWAIT) != 0){ printf("send msg2 error\n"); } if(msgsnd(msg_id,&msg3,sizeof(MSG)-sizeof(long),IPC_NOWAIT) != 0){ printf("send msg3 error\n"); } if(msgsnd(msg_id,&msg4,sizeof(MSG)-sizeof(long),IPC_NOWAIT) != 0){ printf("send msg4 error\n"); } struct msqid_ds ds; if(msgctl(msg_id,IPC_STAT,&ds) != 0){ perror("msgctl error"); } printf("msg total:%ld\n",ds.msg_qnum); printf("msg id:%d\n",msg_id); return 0;}

msg_get.c

/* * =========================================================================== * *       Filename:  msg_get.c *    Description:   *        Version:  1.0 *        Created:  2017年04月10日 22时33分28秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include
#include
#include
#include
#define BUFFER 1024typedef struct{ long type; char content[BUFFER];}MSG;int main(int argc ,char * argv[]){ if(argc < 3){ printf("参数错误"); exit(EXIT_FAILURE); } key_t key = atoi(argv[1]); long type = atoi(argv[2]); printf("key:%d,type:%ld\n",key,type); int msg_id; if((msg_id = msgget(key,0777)) < 0){ perror("get msg error"); } printf("msg_id:%d\n",msg_id); MSG m; if(msgrcv(msg_id,&m,sizeof(MSG)-sizeof(long),type,IPC_NOWAIT) < 0){ perror("get msg error\n"); }else{ printf("msg get type:%ld,content:%s\n",m.type,m.content); } return 0;}

以上就是很简单的关于消息队列的调试代码.很简单.欢迎补充

你可能感兴趣的文章
实验十 算术编码
查看>>
实验二 二维随机变量信息量的计算
查看>>
使用react脚手架创建react项目时发生错误
查看>>
关于setState是异步与同步的
查看>>
56. 合并区间---js解法
查看>>
5. 最长回文子串---js解法
查看>>
USACO 2007 Open Gold/acwing2240:餐饮 (拆点+最大流)‘三分图匹配’
查看>>
那些年你不知道的C++STL进制转换函数
查看>>
区间和并问题 思路加模板整理(校门外的树)
查看>>
C++中next_permutation函数的使用方法、原理及手动实现
查看>>
网络流常用小技巧之 拆点
查看>>
最大权闭合子图
查看>>
最小权点覆盖集 与 最大权独立集
查看>>
POJ 2125 Destroying The Graph && Acwing 2325. 有向图破坏(拆点+最小权点覆盖集)
查看>>
计算几何基础知识整理大全 代码模板与证明过程 (直线、向量、多边形、三维计算几何、凸包、半平面交、最小圆覆盖)
查看>>
计算几何之 判断两线段是否相交 代码模板与证明
查看>>
三维计算几何之三维凸包 增量法
查看>>
MySQL变量,存储过程,函数,流程控制详解(小白都能懂哦)
查看>>
9篇小白都能懂系列博客学完MySQL基础
查看>>
还在为Linux入门发愁?
查看>>