system消息队列,说白了就是内核维护的队列,这个队列的元素是进程发出的一些字符串。通过消息队列,可以实现进程间消息的传递。
对于每个消息队列,内核都维护了下面这个数据结构
struct msqid_ds {
struct ipc_perm msg_perm; //存一些权限,创建信息之类的
struct msg* msg_first; //ptr to first message on queue
struct msg* msg_last; //ptr to last message on queue
msglen_t msg_cbytes; //current # bytes on queue
msgqnum_t msg_qnum; //current # of message on queue
msglen_t msg_qbytes; <span style="white-space:pre"> </span>//max \# of bytes allowed on queue
pid_t msg_lspid; //pid of last msgsnd
pid_t msg_lrpid; //pid of last msgrcv
time_t msg_stime; //time of last msgsnd()
time_t msg_rtime; //time of last msgrcv()
time_t msg_ctime; //time of last msgctl()
};
1.msgget()函数-------建立消息队列
#include<sys/msg.h>
int msgget(key_t key,int oflag);
//若成功返回非负标识符,否则返回-1;
其中 key_t 要么是ftok()的返回值,要么是常量IPC_PRIVATE(0),要么是你随便填的一个非负数.
差别在于:系统通过key值确定你要使用哪个消息队列,两个进程想要使用消息队列通信,必须使用相同的key。
ftok(char * pathname,int id)函数可以通过一致的pathname和id很方便的构造出key;
IPC_PRIVATE 意为私有的,用这个参数得到的消息队列,只能通过fork()在本进程和子进程间使用 注;IPC_PRIVATE值为0
随便填一个非负数,你记住它就行了,在你想要通信的进程的msgget函数中填入相同的数,即可快活的使用消息队列,但!但!!但!!!这么填的话很有可能别的不相干的进程的msgget参数也是这个值,后果就是,这个消息队列中充斥着不同的信息,自己的消息被别的进程读了,别的进程的消息可能又被自己读了,。,。
oflag参数,基本就是: 权限位,IPC_CREAT,IPC_EXCL;
IPC_CREAT 如果消息队列不存在,就创建它。IPC_CREAT一般都与权限位异或,比如 0666|IPC_CREAT
IPC_EXCL 如果消息队列已存在,msgget返回 -1;
2.msgsnd()函数 ------发送消息
#include<sys/msg.h>
int msgsnd(int msqid,const void *ptr,size_t length,int flag);
//成功返回0,失败返回-1
ptr 指向了消息结构体,模板如下
struct msgbuf {
long mtype; // mssage type must be > 0
char mtext[length];// mssage data
};
ptr指向一个long 长整型数,表示消息类型,紧跟其后的就是消息。
length 表示消息类型之后的,消息正文的长度。
flag只有两个参数 0 或 IPC_NOWAIT(非阻塞);
3.msgrcv()函数 -----接收消息
#include <sys/msg.h>
ssize_t msgrcv(int msqid,void *ptr,size_t length,long type ,int flag);
//若成功,返回成功读入的消息正文的字节数,否则返回-1
msqid : 消息队列标识符;
ptr :指向msgbuf结构体的指针;
length :消息的正文长度 ,不包括消息类型long
type; 接收类型, type == 0 返回该队列第一个消息;
type > 0 返回消息类型等于type的第一个消息
type < 0 返回小于等于type绝对值的,最小的消息类型的第一个消息
flag: IPC_NOWAIT 非阻塞
0 do nothing