Linux——进程间通信(消息队列)

消息队列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

1.特点
1.消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。

2.消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。

3.消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取

函数原型:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
		/* 创建或打开消息队列:成功返回队列ID,失败-1*/
       int msgget(key_t key, int msgflg);
第二个参数,msgflg 控制的。它可以取下面的几个值:
IPC_CREAT :
如果消息队列对象不存在,则创建之,否则则进行打开操作;
IPC_EXCL:
和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建之,否则产生一个
错误并返回。


		/* 添加消息:成功返回0, 失败-1*/
       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
        msqid:队列ID  
        *msgp:msgp 指向要发送的消息所在的内存
        msgsz:是要发送信息的长度(字节数)
        msgflg:第四个参数是控制函数行为的标志,可以取以下的值:0,忽略标志位;


		/* 读取消息:成功返回消息数据的长度, 失败-1*/
	   ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
        函数的前三个参数和msgsnd()函数中对应的参数的含义是相同的。第四个参数mtype
指定了函数从队列中所取的消息的类型
        第五个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;

		/* 控制消息队列:成功返回0,失败-1*/
	   int msgctl(int msqid, int cmd, struct msqid_ds *buf);
		函数的第一个参数msgqid 是消息队列对象的标识符。
		第二个参数是函数要对消息队列进行的操作,它可以是:
	**IPC_STAT**
	取出系统保存的消息队列的msqid_ds 数据,并将其存入参数buf 指向的msqid_ds 结构
	中。
	**IPC_SET**
	设定消息队列的msqid_ds 数据中的msg_perm 成员。设定的值由buf 指向的msqid_ds
	结构给出。
	**IPC_RMID**
	将队列从系统内核中删除。

下面用到ftok函数
系统建立IPC通讯 (消息队列、信号量和共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。

头文件
#include <sys/types.h>
#include <sys/ipc.h>
函数原型:
key_t ftok( const char * fname, int id )
fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:
key_t key;
key = ftok(".", 1); 这样就是将fname设为当前目录。
id是子序号。虽然是int类型,但是只使用8bits(1-255)。
在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。
如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。
查询文件索引节点号的方法是: ls -i
当删除重建文件后,索引节点号由操作系统根据当时文件系统的使用情况分配,因此与原来不同,所以得到的索引节点号也不同。

字符的输入与输出使用gets()和puts()的原因:scanf输入字符串(含有空格的字符串,例如:“I love you!”)时,总是在空格处停止扫描

简单的demo:server端可以发送消息给client端,client端可以实时获取打印到终端显示

msg_client.c

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

#define  MSG_FILE "/etc/passwd"

struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[256];    /* message data */
           };


int main()
{

	int msg_ID;

	key_t key;
	key = ftok(MSG_FILE,'z');
	if(key < 0){
		printf("ftok errr!!\n");
	}
	printf("ket :%d\n",key);

	msg_ID = msgget(key,IPC_CREAT|0777);
	if(msg_ID == -1){
		printf("msgget error!!\n");
		perror("why");
		exit(-1);
	}

	struct msgbuf msg_client;
	msg_client.mtype = 888;
while(1){

	msgrcv(msg_ID,&msg_client,sizeof(msg_client.mtext),msg_client.mtype,0);
	//printf("client read_buff:%s\n",msg_client.mtext);
	printf("read form server:");
	puts(msg_client.mtext);
	memset(msg_client.mtext,0,sizeof(msg_client.mtext));
}

	return 0;
}
msg_server.c

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

#define  MSG_FILE "/etc/passwd"

struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[256];    /* message data */
           };


int main()
{

	key_t key = ftok(MSG_FILE,'z');
	if(key < 0){
		printf("ftok error!!\n");
		exit(-1);
	}	
	printf("key:%d\n",key);

	int msg_ID;


	msg_ID = msgget(key,IPC_CREAT|0777);
	if(msg_ID == -1){
		printf("msgget error!!\n");
		perror("why");
		exit(-1);
	}

	struct msgbuf server;
	server.mtype = 888;
while(1){
	
	gets(server.mtext);

	msgsnd(msg_ID,&server,sizeof(server.mtext),0);
	memset(server.mtext,0,sizeof(server.mtext));
}
	return 0;
}

效果大概就这样:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值