Linux消息队列

消息队列 - msgctl - 《Linux API速查手册》 - 书栈网 · BookStackicon-default.png?t=N7T8https://www.bookstack.cn/read/linuxapi/docs-msgctl.md概念:

消息队列是System V IPC对象的一种。

消息队列的使用:

发送端:

1 申请Keyftok()函数深度解析-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/u013485792/article/details/50764224

key_t ftok(const char *pathname, int proj_id);

    其中参数fname是指定的文件名,这个文件必须是存在的而且可以访问的。id是子序号,它是一个8bit的整数。即范围是0~255。当函数执行成功,则会返回key_t键值,否则返回-1。在一般的UNIX中,通常是将文件的索引节点取出,然后在前面加上子序号就得到key_t的值。



有关该函数的三个常见问题:

1.pathname是目录还是文件的具体路径,是否可以随便设置

2.pathname指定的目录或文件的权限是否有要求

3.proj_id是否可以随便设定,有什么限制条件



解答:

   1、ftok根据路径名,提取文件信息,再根据这些文件信息及project ID合成key,该路径可以随便设置。

    2、该路径是必须存在的,ftok只是根据文件inode在系统内的唯一性来取一个数值,和文件的权限无关。

    3、proj_id是可以根据自己的约定,随意设置。这个数字,有的称之为project ID; 在UNIX系统上,它的取值是1到255;

2打开/创建消息队列   msgget

3向消息队列发送消息   msgsnd

接收端:

1打开/创建消息队列   msgget

2从消息队列接收消息   msgrcv

3 控制(删除)消息队列   msgctl

打开/创建消息队列:

 #include <sys/ipc.h>
 #include <sys/msg.h>
 int msgget(key_t key, int msgflg);

  成功时返回消息队列的id,失败时返回EOF
  key 和消息队列关联的key  IPC_PRIVATE 或 ftok
  msgflg  标志位  IPC_CREAT|0666  IPC_CREAT:没有创建,有则打开。

发送消息:

#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd( int msgid, 
            const void *msgp, 
            size_t size,
            int msgflg);
 
  成功时返回0,失败时返回-1。
  msgid   消息队列id
  msgp    消息缓冲区地址
  size    消息正文长度
  msgflg  标志位 0 或 IPC_NOWAIT
  msgflg:
    0:当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列
    IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回

 消息格式:

typedef struct{
long msg_type;
char buf[128];
}msgT;
注意:
1 消息结构必须有long类型的msg_type字段,表示消息的类型。
2消息长度不包括首类型 long
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#include<stdlib.h>

typedef struct
{
	long msg_type;
	char buf[128];
}msgT;

int main()
{
	int msgid;
	
	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	
	//创建队列
	msgid = msgget(key,IPC_CREAT | 0666);
	if(msgid < 0)
	{
		perror("msgget");
		return 0;
	}
	
	//消息填充
	msgT msg;
	msg.msg_type = 1;
	strcpy(msg.buf,"this msg type 1");

	//发送消息
	int ret;
	#define MSGLEN (sizeof(msgT) - sizeof(long))
	
	ret = msgsnd(msgid,&msg,MSGLEN,0);
	if(ret < 0)
	{
		perror("msgsnd");
		return 0;
	}

	//通过ipcs指令查看是否发送

	return 0;
}

 运行结果:

消息的接收:

 #include <sys/ipc.h>
 #include <sys/msg.h>
 int msgrcv(int msgid, 
            void *msgp, 
            size_t size, 
            long msgtype,
            msgflg);

  成功时返回收到的消息长度,失败时返回-1。
  msgid   消息队列id
  msgp   消息缓冲区地址
  size   指定接收的消息长度 
  msgtype   指定接收的消息类型   
  msgflg   标志位  

msgtype:
msgtype=0:收到的第一条消息,任意类型。任意
msgtype>0:收到的第一条 msg_type类型的消息。指定
msgtype<0:接收类型等于或者小于msgtype绝对值的第一个消息。范围
例子:如果msgtype=-4,只接受类型是1、2、3、4的消息 

msgflg:
0:阻塞式接收消息
IPC_NOWAIT:如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG
MSG_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype的消息
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>

typedef struct 
{
	long msg_type;
	char buf[128];
}msgT;

#define MSGLEN (sizeof(msgT)-sizeof(long))

int main()
{
	msgT msg;

	key_t key;
	key = ftok(".",100);

	int msgid;
	msgid = msgget(key,IPC_CREAT|0666);

	int ret;
	while(1)
	{
		ret = msgrcv(msgid,&msg,MSGLEN,0,0);
		if(ret < 0)
		{
			perror("msgrcv");
			return 0;
		}
		printf("msg receive type = %d,buf = %s\n",(int)msg.msg_type,msg.buf);
	}
}

 运行结果:

 消息队列的控制:

 #include <sys/ipc.h>
 #include <sys/msg.h>
 int msgctl(int msgid, int cmd, struct msqid_ds *buf);

  成功时返回0,失败时返回-1。
  buf      存放消息队列属性的地址
  msgid    消息队列id
  cmd      要执行的操作  IPC_STAT / IPC_SET / IPC_RMID(删除)

cmd参数:
IPC_RMID
删除消息队列。从系统中删除给消息队列以及仍在该队列上的所有数据,这种删除立即生效。
仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将出错,并返回EIDRM。
  
IPC_SET
设置消息队列的属性。按照buf指向的结构中的值,来设置此队列的msqid_id结构。

IPC_STAT
读取消息队列的属性。取得此队列的msqid_ds结构,并存放在buf*中。

IPC_INFO
读取消息队列基本情况。

 运行结果:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>

typedef struct 
{
	long msg_type;
	char buf[128];
}msgT;

#define MSGLEN (sizeof(msgT)-sizeof(long))

int main()
{
	msgT msg;

	key_t key;
	key = ftok(".",100);

	int msgid;
	msgid = msgget(key,IPC_CREAT|0666);

	int count = 0;
	int ret;
	while(1)
	{
		ret = msgrcv(msgid,&msg,MSGLEN,-3,0);
		if(ret < 0)
		{
			perror("msgrcv");
			return 0;
		}
		count ++;
		if(count > 3)
		{
			break;
		}
		printf("msg receive type = %d,buf = %s\n",(int)msg.msg_type,msg.buf);
	}

	ret = msgctl(msgid,IPC_RMID,NULL);
	if(ret < 0)
	{
		perror("msgctl");
		return 0;
	}


}

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值