system V 消息队列(msg)

头文件:

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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/msg.h>
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 <stdio.h>
#include <sys/msg.h>
#include <fcntl.h>

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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
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] <pathname> <message> <type>\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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
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] <pathname> <type>\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 <stdio.h>
#include <sys/msg.h>

int main(int argc,char* argv[]){
	int i;
	for(i=1;i<argc;i++){
		msgctl(atoi(argv[i]),IPC_RMID,NULL);
	}
}


获得当前消息队列信息代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>

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);
}





版权声明:本文为lingfeng2019原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。