本文共 5390 字,大约阅读时间需要 17 分钟。
System V Ipc概述:
1:Unix系统存在信号,管道和命名管道等基本通信机制 2:System V引入三种高级进程间通信机制消息队列,共享内存和信号量
IPC对象存在于内核中而不是文件系统中,由用户控制释放,不像管道的释放由内核控制
3:IPC对象用过其标识符来引用和访问,所有IPC对象在内核空间中有唯一性表示ID,在用户空间中的唯一标识为key Linux IPC继承来自System V IpcIPC对象是全部对象
可用ipcs,ipcrm等命令查看或删除 从上面我们可以看到共享内存端.信号量数组和消息队列每个IPC对象的都由get函数创建
msgget,shmget,semget调用get函数时必须制定关键字keyIPC对象的权限和所有者结构体:struct ipc_perm{ uid_t uid; gid_t gid; uid_t cuid; gid_t cgid; mode_t mode;//权限 ......;}
消息队列概述:
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; //消息队列最后改变的时间 ......}
消息队列函数:
打开或者创建消息队列
#includeint 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的值否则查询不到;
消息队列的控制函数:
#includeint 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:删除队列,从系统中删除该消息队列以及仍在该队列上的所有数据
消息队列的发送函数:
消息队列的发送:#includeint 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,则进程 阻塞直到有空间可以容纳要发送的消息 或从系统中删除了此队列 或捕捉到一个信号,并且从信号处理程序返回
消息队列的接受
#includessize_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;}
以上就是很简单的关于消息队列的调试代码.很简单.欢迎补充