【IPC-UNIX网络编程】第6章 System V消息队列

本文介绍了SystemV消息队列的使用,包括msgget函数创建或访问队列,msgsnd函数发送消息,msgrcv函数接收消息,以及msgctl函数对队列进行控制。示例程序演示了如何创建、发送、接收和删除消息队列,展示了这些函数的实际应用。
摘要由CSDN通过智能技术生成

1 概述

System V消息队列使用消息队列标识符标识。具有足够特权的任何进程都可以往一个给定队列放置一个消息 / 读出一个消息。

  • 对于系统中的每个消息队列,内核维护一个定义在<sys/msg.h>头文件中的信息结构:
struct msqid_ds
{
	struct ipc_term msg_perm;  // read_write perms
	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 messages on queue
	msglen_t msg_qbytes;   // 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() (that changed the above)
};

2 msgget函数

msgget函数用于创建一个新的消息队列或访问一个已存在的消息队列。

#include <sys/msg.h>
// 成功返回非负标识符,否则返回-1
int msgget(key_t key, int oflag);  

3 msgsnd函数

使用msgget打开一个消息队列后,使用msgsnd往其上放置一个消息。

#include <sys/msg.h>
// 成功返回0,否则返回-1
int msgsnd(int msqid, const void *ptr, size_t length, int flag);  

4 msgrcv函数

使用msgrcv函数从某个队列中读出一个消息。

#include <sys/msg.h>
// 成功返回读入缓冲区中数据的字节数,否则返回-1
ssize_t msgrcv(int msqid, void *ptr, size_t length, long type, int flag);  
  • ptr参数指定所接收消息的存放位置。
  • length指定了由ptr指向的缓冲区中数据部分的大小。

5 msgctl函数

msgctl函数提供一个消息队列上的各种控制操作。

#include <sys/msg.h>
// 成功返回0,否则返回-1
int msgctl(int msqid, int cmd, struct msqid_ds *buff);

msgctl函数提供3个命令。

  • IPC_RMID: 从系统中删除由msqid指定的消息队列。
  • IPC_SET: 给所指定的消息队列设置其msqid_ds结构的以下4个成员:msg_perm.uid, msg_perm.gid, msg_perm.mode和msg_qbytes。
  • IPC_STAT: (通过buff参数)给调用者返回与所指定消息队列对于的当前msqid_ds结构。
#include "unpipc.h"
int main(int argc, char const *argv[])
{
	int msqid;
	struct msqid_ds info;
	struct msqbuf buf;

	msqid = Msgget(IPC_PRIVATE, SVMSG_MODE | IPC_CREAT);

	buf.mtype = 1;
	buf.mtext[0] = 1;
	Msgsnd(msqid, &buf, 1, 0);

	Msgctl(msqid, IPC_STAT, &info);
	printf("read-write: %03o, cbytes = %lu, qnum = %lu, qbytes = %lu\n",
	        info.msg_perm & 0777, (ulong_t) info.msg_cbytes,
	        (ulong_t) info.msg_qnum, (ulong_t) info.msg_qbytes);
	system("ipcs -q");
	Msgctl(msqid, IPC_RMID, NULL);
	exit(0);
}

6 简单的程序

msgcreate程序:创建一个消息队列
#include "unpipc.h"
int main(int argc, char const *argv[])
{
	int c, oflag, mqid;
	oflag = SVMSG_MODE | IPC_CREAT;
	while ( (c = Getopt(argc, argv, "e")) != -1) {
		switch (c) {
			case 'e':
			   oflag |= IPC_EXCL;
			   break;
		}
	}
	if (optind != argc -1)
		err_quit("usage: msgcreate [-e] <pathname>");
    // ftok - convert a pathname and a project 
    // identifier to a System V IPC key
	mqid = Msgget(Ftok(argv[optind], 0), oflag);
	exit(0);
}
msgsnd程序:
#include "unpipc.h"
int main(int argc, char const *argv[])
{
	int mqid;
	size_t len;
	long type;
	struct msgbuf *ptr;

	if (argc != 4) 
		err_quit("usage: msgsnd <pathname> <#bytes> <type>");
	len = atoi(argv[2]);
	type = atoi(argv[3]);

	mqid = Msgget(Ftok(argv[1], 0), MSG_W);
	// 把一个指定了长度和类型的消息放置到队列中
	ptr = Calloc(sizeof(long) + len, sizeof(char)); // calloc把申请的内存全部初始化为0
	ptr->mtype = type;

	Msgsnd(mqid, ptr, len, 0);
	exit(0);
}
msgrcv程序
#include "unpipc.h"
#define MAXMSG (8192 + sizeof(long))

int main(int argc, char const *argv[])
{
	int c, flag, mqid;
	long type;
	ssize_t n;
	struct msgbuf *buff;

	type = flag = 0;
	while ( (c = Getopt(argc, argv, "nt:")) != -1) {
		switch (c) {
			case 'n':
				flag |=IPC_NOWAIT;
				break;
			case 't':
				type = atol(optarg);
				break;
		}
	}
	if (optind != argc - 1)
		err_quit("usage: msgrcv[-n] [-t type] <pathname>");

	mqid = Msgget(Ftok(argv[optind], 0), MSG_R);
	buff = Malloc(MAXMSG);

	n = Msgrcv(mqid, buff, MAXMSG, type, flag);
	printf("read %d bytes, type = %ld\n", n, buff->mtype);
	exit(0);
}
msgrmid程序
  • 删除一个消息队列,以IPC_RMID命令调用msgctl
#include "unpipc.h"
#define MAXMSG (8192 + sizeof(long))

int main(int argc, char const *argv[])
{
	int mqid;
	if (argc != 2)
		err_quit("usage: msgrmid <pathname>");

	mqid = Msgget(Ftok(argv[1], 0), 0);
	Msgctl(mqid, IPC_RMID, NULL);
	exit(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值