Linux进程IPC浅析[进程间通信SystemV消息队列]
2017-04-10 23:19
609 查看
Linux进程IPC浅析[进程间通信SystemV消息队列]
System V IPC的概述System V IPC对象访问
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<sys/msg.h> 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<sys/msg.h> 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<sys/msg.h> 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<sys/msg.h> 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<stdio.h> #include<stdlib.h> #include<sys/msg.h> #include<string.h> #define BUFFER 1024 typedef 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<stdio.h> #include<stdlib.h> #include<sys/msg.h> #include<string.h> #define BUFFER 1024 typedef 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; }
以上就是很简单的关于消息队列的调试代码.很简单.欢迎补充
欢迎持续访问博客
相关文章推荐
- Linux进程IPC浅析[进程间通信SystemV进程的信号量和信号量集]
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- Linux进程间通信IPC学习笔记之消息队列(SVR4)
- 深入理解Linux进程间通信(IPC)-- Posix消息队列
- Linux进程通信IPC--消息队列MessageQueue
- Linux进程间通信(IPC)编程实践(十二)Posix消息队列--基本API的使用
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- 【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列 分类: Linux --- 应用程序设计 2014-11-11 13:16 71人阅读 评论(0) 收藏
- Linux进程间通信(IPC)编程实践(四) 详解System V消息队列(2)(msgsnd & msgrcv)
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- Linux的进程编程-之二-进程间通信(消息队列)
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- Linux 进程间通信 (IPC) // 消息队列
- Linux进程间通信(IPC)编程实践(五)消息队列实现回射客户/服务器
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- Linux进程间通信IPC学习笔记之消息队列(Posix)
- uc笔记09---进程通信,管道,进程间通信,共享内存,消息队列,信号量,IPC 命令