Linux消息队列之命令行相关

一、消息队列 

(也叫做报文队列)是Unix系统V版本中3种进程间通信机制之一。另外两种是信号灯和共享内存。这些IPC机制使用共同的授权方法。只有通过系统调用将标志符传递给核心之后,进程才能存取这些资源。这种系统IPC对象使用的控制方法和文件系统非常类似。使用对象的引用标志符作为资源表中的索引。

消息队列就是一个消息的链表。就是把消息看作一个记录,并且这个记录具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读出消息。

Linux采用消息队列的方式来实现消息传递。这种消息的发送方式是:发送方不必等待接收方检查它所收到的消息就可以继续工作下去,而接收方如果没有收到消息也不需等待。这种通信机制相对简单,但是应用程序使用起来就需要使用相对复杂的方式来应付了。新的消息总是放在队列的末尾,接收的时候并不总是从头来接收,可以从中间来接收。

消息队列是随内核持续的并和进程相关,只有在内核重起或者显示删除一个消息队列时,该消息队列才会真正被删除。因此系统中记录消息队列的数据结构 (struct ipc_ids msg_ids)位于内核中,系统中的所有消息队列都可以在结构msg_ids中中找到访问入口。

IPC标识符:每一个I P C目标都有一个唯一的I P C标识符。这里所指的I P C目标是指一个单独的消息队列、一个信号量集或者一个共享的内存段。系统内核使用此标识符在系统内核中指明 I P C目标。

IPC 关键字:想要获得唯一的标识符,则必须使用一个 I P C关键字。客户端进程和服务器端进程必须双方都同意此关键字。这是建立一个客户机/服务器框架的第一步。在System V IPC机制中,建立两端联系的路由方法是和I P C关键字直接相关的。通过在应用程序中设置关键字值,每一次使用的关键字都可以是相同的。一般情况下,可以使用f t o k ( )函数为客户端和服务器端产生关键字值。

二、ipcs 命令

命令ipcs用于读取System V IPC目标的状态。


[elink@localhost debug]$ ipcs

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status     
0xe24a5000 1409027    elink      600        24         1                      
0xe24a6000 1114116    elink      600        419432856  37                     

------ Semaphore Arrays --------
key        semid      owner      perms      nsems    
0xe20a2000 557067     elink      600        100      

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages   
0xe24a0100 851968     elink      600        0            0          
0xe24a283c 884737     elink      600        0            0          
0xe24a283d 917506     elink      600        0            0          
0xe24a2838 950275     elink      600        0            0          
0xe24a2839 2293764    elink      600        0            0          
0xa4000501 1015813    elink      600        0            0          
0xa4000601 1048582    elink      600        0            0          
0xe24a2438 1081351    elink      600        0            0          
0xe24a2439 1114120    elink      600        0            0          
0xe24a243a 1146889    elink      600        0            0          
0xe24a243b 1179658    elink      600        0            0          
0xe24a4378 1212427    elink      600        0            0          
0xe24a4379 1245196    elink      600        0            0          
0xe24a46fc 1277965    elink      600        0            0          
0xe24a46fd 1310734    elink      600        0            0          
0xe24a25c8 1343503    elink      600        0            0          
0xe24a25c9 1376272    elink      600        0            0          
0xe24a262c 1409041    elink      600        0            0          
0xe24a262d 1441810    elink      600        0            0          
0xe24a2c08 1474579    elink      600        0            0          
0xe24a2c09 1507348    elink      600        0            0          
0xe24a243c 1540117    elink      600        0            0          
0xe24a243d 1572886    elink      600        0            0          
0xe24a46fe 1835031    elink      600        0            0          
0xe24a46ff 1867800    elink      600        0            0          
0x0a30a68c 1966105    elink      660        0            0          
0x85eb568c 1998874    elink      660        0            0          
0xd327768c 2031643    elink      660        0            0          
0x7a8c768c 2064412    elink      660        0            0          
0xea43668c 2097181    elink      660        0            0          
0x3076f68c 2162718    elink      660        0            0          
0x7537668c 2195487    elink      660        0            0          
0xa557768c 2228256    elink      660        0            0          
0x87f0468c 2261025    elink      660        0            0          

[elink@localhost debug]$ netstat -an|grep 50001
tcp        0      0 192.168.17.10:64206         222.66.233.201:50001        ESTABLISHED
[elink@localhost debug]$ ipcs

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status     
0xe24a5000 1409027    elink      600        24         1                      
0xe24a6000 1114116    elink      600        419432856  47                     

------ Semaphore Arrays --------
key        semid      owner      perms      nsems    
0xe20a2000 557067     elink      600        100      

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages   
0xe24a0100 851968     elink      600        0            0          
0xe24a283c 884737     elink      600        0            0          
0xe24a283d 917506     elink      600        0            0          
0xe24a2838 950275     elink      600        0            0          
0xe24a2839 2293764    elink      600        0            0          
0xa4000501 1015813    elink      600        0            0          
0xa4000601 1048582    elink      600        0            0          
0xe24a2438 1081351    elink      600        0            0          
0xe24a2439 1114120    elink      600        0            0          
0xe24a243a 1146889    elink      600        0            0          
0xe24a243b 1179658    elink      600        0            0          
0xe24a4378 1212427    elink      600        0            0          
0xe24a4379 1245196    elink      600        0            0          
0xe24a46fc 1277965    elink      600        0            0          
0xe24a46fd 1310734    elink      600        0            0          
0xe24a25c8 1343503    elink      600        0            0          
0xe24a25c9 1376272    elink      600        0            0          
0xe24a262c 1409041    elink      600        0            0          
0xe24a262d 1441810    elink      600        0            0          
0xe24a2c08 1474579    elink      600        0            0          
0xe24a2c09 1507348    elink      600        0            0          
0xe24a243c 1540117    elink      600        0            0          
0xe24a243d 1572886    elink      600        0            0          
0xe24a46fe 1835031    elink      600        0            0          
0xe24a46ff 1867800    elink      600        0            0          
0x0a30a68c 1966105    elink      660        0            0          
0x85eb568c 1998874    elink      660        0            0          
0xd327768c 2031643    elink      660        0            0          
0x7a8c768c 2064412    elink      660        0            0          
0xea43668c 2097181    elink      660        0            0          
0x3076f68c 2162718    elink      660        0            0          
0x7537668c 2195487    elink      660        0            0          
0xa557768c 2228256    elink      660        0            0          
0x87f0468c 2261025    elink      660        0            0          
0xffffe6e9 2326562    elink      660        0            0          
0x00000039 2359331    elink      660        0            0          

三、消息队列的主要调用

内核中实现消息传递机制的代码基本上都在文件ipc/msg.c中,消息队列的主要调用有下面4个,这里只作简单介绍:

(1)msgget:调用者提供一个消息队列的键标 (用于表示个消息队列的唯一名字),当这个消息队列存在的时候, 这个消息调用负责返回这个队列的标识号;如果这个队列不存在,就创建一个消息队列,然后返回这个消息队列的标识号 ,主要由sys_msgget执行。

(2)msgsnd:向一个消息队列发送一个消息,主要由sys_msgsnd执行。

(3)msgrcv:从一个消息队列中收到一个消息,主要由sys_msgrcv执行。

(4)msgctl:在消息队列上执行指定的操作。根据参数的不同和权限的不同,可以执行检索、删除等的操作,主要由sys_msgctl执行。

四、消息队列的应用例子

下面的例子很好的演示了创建、发送、读取、改变权限以及删除消息队列各种操作:

 

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

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

#define MAX_SEND_SIZE 2000

struct mymsgbuf {
	long mtype;
	char mtext[MAX_SEND_SIZE];
};

void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text);
void read_message(int qid, struct mymsgbuf *qbuf, long type);
void remove_queue(int qid);
void change_queue_mode(int qid, char *mode);
void usage(void);

/**
*执行举例:./ipcs r 1998 104
*入参:
*			argv[1]		'r' or 's' or 'm' or 'd'
*			argv[2]		消息队列id
*			argv[3]		mtype
*			argv[4]		msg_content(仅当要发送消息时使用)
*/
int main(int argc, char *argv[])
{
	//key_t key;
	int msgqueue_id;
	struct mymsgbuf qbuf;

	if(argc == 1)
		usage();

#if 0
	/* Create unique key via call to ftok() */
	key = ftok(".", 'm');/*m=ox(6D)*/
#endif

	/* Open the queue - create if necessary */
	if((msgqueue_id = msgget(*argv[2], IPC_CREAT|0660)) == -1)

	{
		perror("msgget error\n");
		exit(1);
	}else{
		printf("msgget success\n");
	}
	
	printf("you choose :%d\n",tolower(*argv[1]));
	
	switch(tolower(*argv[1]))
	{
		case 's': send_message(msgqueue_id, (struct mymsgbuf *)&qbuf,atol(argv[3]), argv[4]);
		break;
		case 'r': read_message(msgqueue_id, &qbuf, atol(argv[2]));
		break;
		case 'd': remove_queue(msgqueue_id);
		break;
		case 'm': change_queue_mode(msgqueue_id, argv[2]);
		break;

		default: usage();

	}

	return(0);
	}

void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text)
{
	/* Send a message to the queue */
	printf("Sending a message!\n");
	qbuf->mtype = type;
	strcpy(qbuf->mtext, text);

	if((msgsnd(qid, (struct msgbuf *)qbuf,strlen(qbuf->mtext)+1, 0)) ==-1)
	{
	perror("msgsnd");
	exit(1);
	}
}

void read_message(int qid, struct mymsgbuf *qbuf, long type)
{
	/* Read a message from the queue */
	printf("Reading a message!\n");
	qbuf->mtype = type;
	msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0);

	printf("Type: %ld\n", qbuf->mtype);
	printf("Text: %sn\n",qbuf->mtext);
}

void remove_queue(int qid)
{
	/* Remove the queue */
	msgctl(qid, IPC_RMID, 0);
}

void change_queue_mode(int qid, char *mode)
{
	struct msqid_ds myqueue_ds;

	/* Get current info */
	msgctl(qid, IPC_STAT, &myqueue_ds);

	/* Convert and load the mode */
	sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode);

	/* Update the mode */
	msgctl(qid, IPC_SET, &myqueue_ds);
}

void usage(void)
{
	fprintf(stderr, "msgtool - A utility for tinkering with msg queuesn\n");
	fprintf(stderr, "nUSAGE: msgtool\n");
	fprintf(stderr, "(s)end \n");
	fprintf(stderr, " (r)ecv\n");
	fprintf(stderr, " (d)elete\n");
	fprintf(stderr, " (m)ode \n");
	exit(1);
}



程序保存为 ipcs.c

编译:gcc -o ipcs ipcs.c

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值