linux 进程间通信 消息队列
来源:互联网 发布:java中交换两个数 编辑:程序博客网 时间:2024/05/17 06:53
消息队列常用操作函数如下:
#include <sys/msg.h> #include <sys/types.h> #include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id); int msgget(key_t key, int msgflg); int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg); int msgsnd(int msqid, const void *msg_ptr, size_t msg_sz, int msgflg); int msgctl(int msqid, int cmd, struct msqid_ds *buf);
IPC对象数据结构:
内核为每个IPC对象维护一个数据结构
struct ipc_perm { key_t __key; /* Key supplied to xxxget(2) */ uid_t uid; /* Effective UID of owner */ gid_t gid; /* Effective GID of owner */ uid_t cuid; /* Effective UID of creator */ gid_t cgid; /* Effective GID of creator */ unsigned short mode; /* Permissions */ unsigned short __seq; /* Sequence number */};struct msqid_ds { struct ipc_perm msg_perm; /* Ownership and permissions */ time_t msg_stime; /* Time of last msgsnd(2) */ time_t msg_rtime; /* Time of last msgrcv(2) */ time_t msg_ctime; /* Time of last change */ unsigned long __msg_cbytes; /* Current number of bytes in queue (nonstandard) */ msgqnum_t msg_qnum; /* Current number of messages in queue */ msglen_t msg_qbytes; /* Maximum number of bytes allowed in queue */ pid_t msg_lspid; /* PID of last msgsnd(2) */ pid_t msg_lrpid; /* PID of last msgrcv(2) */};
msgget函数
功能:用来创建和访问一个消息队列
原型
int msgget(key_t key, int msgflg);
参数
key: 某个消息队列的名字
msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该消息队列的标识码;失败返回-1
msgget函数参数关系图:
功能:消息队列的控制函数
原型
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数
msqid: 由msgget函数返回的消息队列标识码
cmd:是将要采取的动作,(有三个可取值)
返回值:成功返回0,失败返回-1
msgsnd函数
功能:把一条消息添加到消息队列中
原型
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数
msgid: 由msgget函数返回的消息队列标识码
msgp:是一个指针,指针指向准备发送的消息,
msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
返回值:成功返回0;失败返回-1
msgflg=IPC_NOWAIT表示队列满不等待,返回EAGAIN错误。
消息结构在两方面受到制约。首先,它必须小于系统规定的上限值;其次,它必须以一个long int长整数开始,接收者函数将利用这个长整数确定消息的类型
消息结构参考形式如下:
struct msgbuf
{
long mtype;
char mtext[100];
}
msgrcv函数
功能:是从一个消息队列接收消息
原型
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数
msgid: 由msgget函数返回的消息队列标识码
msgp:是一个指针,指针指向准备接收的消息,
msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
msgtype:它可以实现接收优先级的简单形式
msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事
返回值:成功返回实际放到接收缓冲区里去的字符个数,失败返回-1
msgtype=0返回队列第一条信息
msgtype>0返回队列第一条类型等于msgtype的消息
msgtype<0返回队列第一条类型小于等于msgtype绝对值的消息,并且是满足条件的消息类型最小的消息
msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。
msgflg=MSG_NOERROR,消息大小超过msgsz时被截断
msgtype>0且msgflg=MSG_EXCEPT,接收类型不等于msgtype的第一条消息。
msg01.c
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdio.h>int main(int argc, char *argv[]){ int msg_id = msgget( 0x1234, 0666); if(msg_id == -1) { printf("msgget error\n"); return -1; } return 0;}
msg02.c
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdio.h>#include <errno.h>int main(int argc, char *argv[]){ int msg_id = msgget( 0x1234, 0666); if(msg_id == -1) { printf("msgget error\n"); if(errno == ENOENT ) { printf("No message queue exists for key\n"); return -1; } } return 0;}
msg03.c
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdio.h>#include <errno.h>int main(int argc, char *argv[]){ int msg_id = msgget( 0x1234, IPC_CREAT | 0666); if(msg_id == -1) { printf("msgget error\n"); if(errno == ENOENT ) { printf("No message queue exists for key\n"); return -1; } } printf("get msg queue id = %d\n", msg_id); struct msqid_ds mq; if(msgctl(msg_id, IPC_STAT, &mq) != 0) { //printf("msgctl error\n"); perror("msgctl error:\n"); return -1; } int mode = mq.msg_perm.mode; int curretSize = mq.__msg_cbytes; int currentNumber = mq.msg_qnum; printf("mode = %o, curretSize = %d, currentNumber = %d\n", mode, curretSize, currentNumber); mq.msg_perm.mode = 0644; if(msgctl(msg_id, IPC_SET, &mq) != 0) { perror("msgget err"); return -1; } return 0;}
msg04.c
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdio.h>#include <errno.h>int main(int argc, char *argv[]){ int msg_id = msgget( 0x1234, IPC_CREAT | 0666); if(msg_id == -1) { printf("msgget error\n"); if(errno == ENOENT ) { printf("No message queue exists for key\n"); return -1; } } printf("get msg queue id = %d\n", msg_id); struct msqid_ds mq; if(msgctl(msg_id, IPC_STAT, &mq) != 0) { //printf("msgctl error\n"); perror("msgctl error:"); return -1; } int mode = mq.msg_perm.mode; int curretSize = mq.__msg_cbytes; int currentNumber = mq.msg_qnum; printf("mode = %o, curretSize = %d, currentNumber = %d\n", mode, curretSize, currentNumber); if(msgctl(msg_id, IPC_RMID, NULL) != 0) { perror("msgctl error:"); return -1; } return 0;}
消息队列的简单应用:
消息队列实现回射客户/服务器
echoclient.c
#include <unistd.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0)#define MSGMAX 8192struct msgbuf {long mtype; /* message type, must be > 0 */char mtext[MSGMAX]; /* message data */};//思路://客户端发给服务器消息类型总是1//服务器端回给客户端的type是对方进程号//相当于服务器端 从消息队列中收消息,然后服务器端分类型回复客户端(通过消息队列)//n个进程通过消息队列进行交换//有没有产生死锁的可能//n个客户端向服务器发送消息(本质上是向内核消息队列发送消息),若消息队列满了;服务区回射时,会阻塞。。造成程序死锁//即使,非阻塞。。。仍然回阻塞。。void echo_cli(int msgid){int n;int pid;pid = getpid();struct msgbuf msg;memset(&msg, 0, sizeof(msg));//消息内容由:自己的pid+键盘输入*((int*)msg.mtext) = pid;//消息类型 1msg.mtype = 1;while (fgets(msg.mtext+4, MSGMAX, stdin) != NULL){if (msgsnd(msgid, &msg, 4+strlen(msg.mtext+4), 0) < 0)ERR_EXIT("msgsnd");//前四个字节是自己的pidmemset(msg.mtext+4, 0, MSGMAX - 4);if ((n = msgrcv(msgid, &msg, MSGMAX, pid, 0)) < 0) ERR_EXIT("msgsnd");fputs(msg.mtext+4, stdout);memset(msg.mtext+4, 0, MSGMAX-4);}}int main(int argc, char *argv[]){int msgid;msgid = msgget(0x1234, 0);if (msgid == -1)ERR_EXIT("msgget");echo_cli(msgid);return 0;}
echoserver.c
#include <unistd.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0)#define MSGMAX 8192struct msgbuf {long mtype; /* message type, must be > 0 */char mtext[MSGMAX]; /* message data */};void echo_srv(int msgid){int n;struct msgbuf msg;memset(&msg, 0, sizeof(msg));while (1){if ((n = msgrcv(msgid, &msg, MSGMAX, 1, 0)) < 0)ERR_EXIT("msgsnd");int pid;pid = *((int*)msg.mtext);fputs(msg.mtext+4, stdout);msg.mtype = pid;msgsnd(msgid, &msg, n, 0);}}int main(int argc, char *argv[]){int msgid;msgid = msgget(0x1234, IPC_CREAT | 0666);if (msgid == -1)ERR_EXIT("msgget");echo_srv(msgid);return 0;}
1 0
- Linux进程间通信: 消息队列
- Linux进程间通信: 消息队列
- linux进程间通信之消息队列
- linux C-(进程间通信 消息队列)
- linux进程间通信之消息队列
- Linux高级进程间通信:消息队列
- linux进程间通信之消息队列
- Linux进程间通信之消息队列
- Linux消息队列完成进程间通信
- linux 进程间通信之消息队列
- Linux环境进程间通信-消息队列
- Linux 进程间通信--- 消息队列
- linux进程间通信之消息队列
- linux进程间通信之消息队列
- Linux进程间通信(5):消息队列
- Linux 进程间通信 (IPC) // 消息队列
- linux进程间通信之消息队列
- Linux进程间通信-消息队列
- ios-文件读写
- 理解 pkg-config 工具
- Java中的自动装箱与拆箱
- 关于数字的智力题-三个女儿的年龄
- 冒泡排序
- linux 进程间通信 消息队列
- ehcache集群详解一(支持的集群类型)
- Jetty的SelectChannelConnector分析
- 解决PL/SQL Developer 连接oracle 11g 64位中的问题
- 084 Largest Rectangle in Histogram [Leetcode]
- [LeetCode] Clone Graph
- Java NIO系列教程(八) SocketChannel
- 相机开发(聚焦、横竖屏拍照、照片存储、连续拍照等)
- JAVA语言的特点:C++--