头文件:
sys/msg.h
查看:
ipcs命令
结构体:
自定义消息缓冲区结构msgbuf:
mtype:
消息类型(必须是long型;必须是结构体第一个变量)。
mtext:
消息数据(可以随意定义)。
例子:
struct msgbuf{
long mtype;/* must > 0 */
char mtext;/* data */
};
创建消息队列/消息队列ID获取:
int msgget(key_t key,int msgflg);
key:
IPC键(两种获取方式)。
1.key_t ftok(char* path,int id);
(path,id随意指定。path不存在则返回的key是-1)
2.IPC_PRIVATE
(通常用于亲缘进程)。
msgflg:
IPC_CREAT创建
IPC_CREAT|TPC_EXCL
权限:
用户读 用户写 组读 组写 其他读 其他写
宏 MSG_R MSG_W MSG_R>>3 MSG_W>>3 MSG_R>>6 MSG_W>>6
数值 0400 0200 0040 0020 0004 0002
可以使用八进制数字
例如:
0666
0表示八进制数字
第一个6表示创建者权限为读写(6=4+2)
第二个6表示同组权限为读写(6=4+2)
第三个6表示其他权限为读写(6=4+2)
返回值:
-1—————失败
非负整数——消息队列标识
代码:
IPC键为IPC_PRIVATE:
#include
#include
#include
#include
#include
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
int main(){
int id = msgget(IPC_PRIVATE,O_CREAT|O_RDWR|0644);
if(-1 == id){
perror("msgget error");
return 1;
}
char str[] = "this is msg";
struct msgbuf* buf = malloc(sizeof(str)+sizeof(long));
buf->mtype= 7;
strcpy(buf->mtext,str);
if(!fork()){
sleep(3);
msgsnd(id,buf,sizeof(str),0);
}else{
// sleep(1);
bzero(buf,sizeof(str)+sizeof(long));
msgrcv(id,buf,sizeof(str),-11,0);
printf("mtype:%d\nrecv :%s\n",buf->mtype,buf->mtext);
}
msgctl(id,IPC_RMID,NULL);
}
IPC键为key:
#include
#include
#include
int main(int argc,char* argv[]){
key_t key = ftok(argv[1],1);//argv【1】为已存在的一个路径。通过相同路径生成的key进行通信。
if(-1 == key){
perror("ftok error");
return 1;
}
int id = msgget(ftok(argv[1],1),IPC_CREAT|O_RDWR|0644);
if(-1 == id){
perror("msgget error");
return 1;
}
printf("msqid:%d\n",id);
}
发送消息:
int msgsnd(int msgid,const void* msgbuf,size_t msgsz,int msgflg);
msgid:
消息队列标识。
msgbuf:
消息队列结构体(以一个长整型成员变量开始的结构体)。
msgsz:
消息长度。(不包括长整型变量)。
msgflg:
控制函数行为:
0—————————忽略。
IPC_NOWAIT————如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。
MSG_NOERROR——如果函数获取的消息长度大于msgsz,将只返回msgsz长度的信息,剩下的部分被丢弃了。
MSG_EXCEPT———当msgtyp≥0时,接收类型不等于msgtype的第一条消息。
返回值:
0——成功
-1——失败
代码:
(注意,要用root用户再能发送,否则权限不够;路径是真实存在的)
#include
#include
#include
#include
#include
#include
struct msgbuf{
long mtype;
char mtext[1];
};
int main(int argc,char* argv[]){
int c,flag = 0;
while((c = getopt(argc,argv,"n")) !=-1){
switch(c){
case 'n':
flag=IPC_NOWAIT;
break;
}
}
if(optind != argc - 3){
printf("usage:%s [-n] \n",argv[0]);
return 1;
}
int id = msgget(ftok(argv[optind],1),O_WRONLY);
if(-1 == id){
perror("msgget error");
return 1;
}
size_t msglen = strlen(argv[optind+1])+1;
struct msgbuf* buf = malloc(sizeof(long)+msglen);
buf->mtype = atoi(argv[optind+2]);
strcpy(buf->mtext,argv[optind+1]);
if(-1 == msgsnd(id,buf,msglen,flag)){
perror("fcntl error");
return 1;
}
接收消息:
int msgrcv(int msgid,void* msgbuf,size_t msgsz,long int msgtype,int msgflg);
msgid:
消息队列标识。
msgbuf:
消息结构体。
msgsz:
消息长度(不包括长整型变量)。
msgtype:
接收优先级。
0————获取队列中优先级数最小的消息。
大于0——获取具有相同消息类型的第一个信息。
小于0——获取类型等于或小于msgtype的绝对值的消息(优先级数从小到大输出)。
msgflg:
控制函数行为(同发送消息中的msgflg)。
返回值:
非负整数——接收到的消息长度。
-1—————失败。
代码:
(要用root用户接受,头则权限不够;路径必须与发送路径一致)
#include
#include
#include
#include
#include
#include
struct msgbuf{
long mtype;
char mtext[1];
};
int main(int argc,char* argv[]){
int c,flag = 0;
while((c = getopt(argc,argv,"n")) !=-1){
switch(c){
case 'n':
flag=IPC_NOWAIT;
break;
}
}
if(optind != argc - 2){
printf("usage:%s [-n] \n",argv[0]);
return 1;
}
int id = msgget(ftok(argv[optind],1),O_RDONLY);
if(-1 == id){
perror("msgget error");
return 1;
}
size_t msglen = BUFSIZ;
struct msgbuf* buf = malloc(sizeof(long)+msglen);
if(-1 == msgrcv(id,buf,msglen,atoi(argv[optind+1]),flag)){
// if(-1 == msgrcv(id,buf,msglen,-10,flag)){
perror("fcntl error");
return 1;
}
printf("read:%s",buf->mtext);
}
消息控制:
int msgctl(int msgid,int cmd,struct msqid_ds* buf);
msgid:
消息队列标识。
cmd:
IPC_STAT——获取当前消息队列控制信息。
IPC_SET——设置当前消息队列控制信息。
IPC_RMID——删除消息队列。
buf:
消息队列模式结构:
msg_perm.mode——消息队列读写模式。
msg_qbytes————队列最大大小。
msg_cbytes————当前队列大小。
msg_qnum————当前队列消息数。
结构体:
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) */
};
返回值:
0——成功
-1——失败
例子:
删除消息队列:
msgctl(msqid,IPC_RMID,NULL);
代码:
#include
#include
int main(int argc,char* argv[]){
int i;
for(i=1;i
获得当前消息队列信息代码:
#include
#include
#include
#include
#include
int main(int argc,char* argv[]){
key_t key = ftok(argv[1],1);
if(-1 == key){
perror("ftok error");
return 1;
}
int id = msgget(ftok(argv[1],1),O_RDWR);
if(-1 == id){
perror("msgget error");
return 1;
}
struct msqid_ds ds;
msgctl(id,IPC_STAT,&ds);
printf("msg_qnum:%ld msg_qsize:%ld msg_cbyte:%ld\n",ds.msg_qnum,ds.msg_qbytes,ds.__msg_cbytes);
}