监听队列中linux方法ss -a,Linux进程间通信----消息队列

一、消息队列的相关概念

《Advanced Programming in the UNIX Environment》: A message queue is a linked list of message stored within the kernel and identified by a message queue identifier .We'll call the message queue just a queue and its identifier a queue ID.

《LINUX C 编程从初学到精通》:消息队列就是一个消息的链表,可以把消息看做一个记录,具有特定结构的格式及特定的优先级。对消息队列有写权限的进程可以向其中按照一定的规则添加新消息。对消息队列有读写权限的进程可以从消息队列中读取消息,消息队列是内核持续的。

二、消息队列的运行机制

消息队列就是一个消息的链表,每个消息队列都有一个队列头,用结构struct msg_queue来描述,队列头中包含了该消息队列的大部分信息,包括消息队列键值/用户ID,组ID,消息队列中消息数目等。

One more thing about System VIPC:when you create a message queue ,it doesn't go away until you destroy it,All the process that have ever used it can quit,but the queue will exit.A good practice is to use the ipcs command to check if any of your unused message queue are just floating around out there.You can destory them with the ipcrm command,which is preferable to getting a vist frome the sysadmin telling you've grabbed every available message queue on the system.

结构体msg_queue 用来描述消息队列头,存在于系统空间,定义如下:

点击(此处)折叠或打开

struct msg_queue

{

struct ipc_perm q_perm;

time_t q_stime;                         /*last msgrcv time*/

time_t q_rtime;                         /*last msgrcv time*/

tiem_t q_ctime;                         /*last change time*/

unsigned long q_cbytes;                 /*current number of bytesonqueue*/

unsigned long q_qnum;                   /*number of messageinqueue*/

unsigned long q_qbytes;                 /*max number of bytes on queue*/

pid_t q_lspid;                          /*pid of last msgsnd*/

pid_t q_lrpid;                          /*last receive pid*/

struct list_head q_messages;

struct list_head q_recivers;

struct list_head q_senders;

};

三、功能函数

1.Are you the key Master?

函数名称

key_t  ftok(char *pathname,char proj)

头文件

#include

#include

功能介绍

获得特定文件名的键值,ftok 返回路径pathname相对应的一个键值,该函数并不直接对消息队列操作,但在调用msgget来获得消息队列的标识符前,往往要调用该函数。

输入参数

*pathname: 文件路径,文件必须是存在的,而且是可以访问的

*proj:   1到255

输出参数

None

return

若成功则返回消息队列的一个键值,若失败返回-1

注意

2.Where is my queue

函数名称

int msgget (key_t key,int msgflag)

头文件

#include

# include  

# inlclude

功能介绍

创建或打开一个消息队列

输入参数

key:键值,有ftok 获得。key is a systyem-wide unique identifier describing the queue you want to connect to (or create).Every other process that wants to connect to this queue will have to use the same key.

msgflg:   参数是一些标志为,可以取指:IPC_CREAT/IPC_EXCL,IPC_NOWAIT或三者的罗辑或结果.The queue permission are the same as standard file permissions-queues take on the user-id and group-id of the program that created them.

输出参数

None

return

success:与该键值key相对应的消息队列标识符(ID)

failure:  -1,保存在 errno

注意

3 Sending to the queue

当你通过msgget()函数创建或者链接了消息队列的时候,此时此刻以及做好准备去发送或者接受消息了,首先,让我们来发送消息。每一则消息都包括2部分,这两部分是通过结构体struct msgbuf 来定义的

点击(此处)折叠或打开

struct msgbuf

{

long mtype;          /*mytype is used later when retrieving message from the queue.and can be set to any positive number */

char mtex[1]; /*mtex is the data this will be add to the queue*/

}

当然也可以用任何的structure 来存放消息队列,只要第一个参数是long类型的就可以。比如:

点击(此处)折叠或打开

struct priate_msgbuf

{

long mtype; /*must be positive*/

structure priate_info{

char name[30];

char ship_type;

int notoriety;

int cruelty;

int booty_value;

}info;

}

函数名称

int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg)

头文件

#include

#include    

#include  

函数功能

向消息队列发送数据

输入参数

msgid: the message queue identifier returned by msgget();

*msgp:the pointer to the data you want to put on the queue.

msgsz:the size in bytes of the data to add to the queue(not counting the size of the mtype member)

msgflg:用于指定消息队列满时的处理方法。

输出参数

None

return

成功:返回 0

失败:返回-1

注意事项

4.Receiving  from  the queue

函数名称

int msgrcv (int msqid, void *prt,size_t nbytes,long type,int flags);

头文件

#include #include #include

函数功能

从消息队列接受数据。

输入参数

msqid : the message queue identifier returned by msgget();

*prt    : 指向存放消息的缓冲区

nbytes: 是以字节表示的要接受的消息的数据长度。

type   : 表示要接受的消息类型

flags  :用于指定消息队列满时的处理方法

返回参数

None

return

成功:0

失败:-1

注意

None

5.Destroying a message queue

The message queue will stick around until you explicitly remove them;it is important that you do this so you don't waste system resources.OK,so you've been using this message queue all day ,and it's getting old,You want to oblierate it.There are two ways:

1.Use Unix command ipcs to get a list of defined message queues,then use the command ipcrm to delete the queue.

2.Write a program to do it for you.

Often ,the latter choice is the most appropriate ,since you might want your program to clean up the queue at some time or another.To do this requires the introduction of another function:msgctl().

函数名称

int msgctl(int msqid ,int cmd,struct msqid_ds *buf)

头文件

#include

函数功能

消息队列的操作函数,具体见

输入参数

msqid: the queue identifier obtained from msgget().

cmd   :this is a important argument that tells msgctl() how to behave.共有3中操作,它们分别是:

IPC_STAT: 该命令用来获取消息队列信息,返回的信息存储在buf指向的msqid_ds 结构中。

IPC_SET :  该命令用来设置消息队列的属性,要设置的属性存储在buf 指向的msgqid_ds 结构中;可设置属性包括 msg_perm.uid/msg_perm.gid/msg_perm.mode及msg_qbytes,同时,也影向msg_ctime成员。

IPC_RMID:    删除msqid标识的消息队列。

输出参数

None

return

成功返回:0

失败返回:-1

注意

流程示意图

4f4fae2d7b4fc17efc72330e95e8716b.png

四、简单例程

此实例是一个简单的消息队列实时聊天通讯程序,发送端每发送一个消息都会立即被接受端读取,在没有消息在队列中时,将处于阻塞状态,发送端发送“end”,接收端读取之后执行删除消息队列的操作。

msg_send_example.c 消息发送端:

点击(此处)折叠或打开

#include

#include

#include

#include

#include

#include

#include

#include

#include

typedef struct

{

long mytpe;

char string[100];

}msg_structure;

int main(int argv,char**argc)

{

int msgid;

key_t key;

msg_structure msg_re;

int size;

int i;

if((key = ftok("test.txt",'B')) == -1)

{

perror("ftot");

exit(1);

}

if(msgid = msgget(key,0644|IPC_CREAT) == -1)

{

perror("msgget");

exit(1);

}

size = sizeof(msg_structure) - sizeof(long);

while(1)

{

printf("Enter the mssage to send:");

for(i=0;(msg_re.string[i]=getchar())!='\n';i++)

{

size = sizeof(msg_structure) - sizeof(long);

}

if(msgsnd(msgid,&msg_re,size,IPC_NOWAIT) == -1)

{

perror("Send message failed");

exit(1);

}

memset(msg_re.string,0,sizeof(msg_re.string));

}

return 1;

}

接收端:msg_receiver_example.c

点击(此处)折叠或打开

#include

#include

#include

#include

#include

#include

#include

typedef struct

{

long mytpe;

char string[100];

}msg_structure;

int main(int argv,char **argc)

{

int msgid;

key_t key;

int size;

int i;

char *p = "end\n";

int ret;

msg_structure msg_rebuf;

if((key = ftok("test.txt",'B')) == -1)

{

perror("ftot");

exit(1);

}

if(msgid = msgget(key,0644) == -1)

{

perror("msgget");

exit(1);

}

size = sizeof(msg_rebuf) - sizeof(long);

memset(msg_rebuf.string,0,sizeof(msg_rebuf.string));

while(1)

{

printf("Receive message:");

if(msgrcv(msgid,&msg_rebuf,size,0,0)==-1)

{

perror("msgrcv");

exit(1);

}

printf("%s\n",msg_rebuf.string);

ret = strcmp(p,msg_rebuf.string);

if(ret == 0)

{

// printf("ret=%d\n",ret);

ret = msgctl(msgid,IPC_RMID,NULL);

if(ret == -1)

{

perror("msgctl");

exit(1);

}

printf("snowstorm\n");

return 1;

}

memset(msg_rebuf.string,0,sizeof(msg_rebuf.string));

}

}

运行结果:

gcc  msg_send_example.c -o send

gcc msg_receiver_example.c -o receiver

./send

Enter the message to send : hello

./receiver

Receive message:hello

五、总结

该简单例程基本阐述清楚了消息队列的运行机制,但是有一个BUG,始终找不到解决的办法,只好暂且放到一边,在第一次运行的时候,没有问题,发送数据,接受数据正常自如,发送端发送“end”,接受端接收到后执行删除任务,如果有哪位朋友指点一下,十分感谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值