2008-07-22 16:22
消息队列就是消息的一个链表,它允许一个或多个进程向它写消息,一个或多个进程从中读消息。具有
一定的FIFO的特性,但是可实现消息的随即查询。这些消息存在于内核中,由“队列ID”来标识。
消息队列的实现包括创建和打开队列、添加消息、读取消息和控制消息队列这四种操作。
msgget:创建和打开队列,其消息数量受系统限制。
msgsnd:添加消息,将消息添加到消息队列尾部。
msgrcv:读取消息,从消息队列中取走消息。
msgctl:控制消息队列。
int msgget (key_t key, int flag)
key:返回新的或已有队列的ID,IPC_PRIVATE
int msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int flag)
其中:msqid是消息队列的队列ID;
msgp是消息内容所在的缓冲区;
msgsz是消息的大小;
msgflg是标志,IPC_NOWAIT若消息并没有立即发送而调用进程会立即返回。
int msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,long msgtyp, int flag)
msqid是消息队列的引用标识符;
msgp是接收到的消息将要存放的缓冲区;
msgsz是消息的大小;
msgtyp是期望接收的消息类型;
int msgctl (int msqid, int cmd, struct msqid_ds *buf)
msqid是消息队列的引用标识符;
cmd是执行命令;
buf是一个缓冲区。
cmd参数指定对于由msqid规定的队列要执行的命令:
IPC_STAT 取此队列的msqid_ds结构,并将其存放在buf指向的结构中。
IPC_SET 按由buf指向的结构中的值,设置与此队列相关的结构中的下列四个字段:
msg_perm.uid、msg_perm.gid、msg_perm;mode和msg_qbytes。此命令只能由下列两种进程执行:一种是其有效 用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。只有超级用户才能增加msg_qbytes的值。
IPC_RMID 从系统中删除该消息队列以及仍在该队列上的所有数据。这种删除立即生效。仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将出错返回 EIDRM。
此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。
msgflg是标志。
具体看例子:
mesg_que_send.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
key_t key;
int msgkey;
pid_t pid;
int count=0;
struct msgbuf{
int mtype;
pid_t from;
int count;
char mtext[50];
}wmsg;
key=ftok("/home/yandongsheng/",10);
pid=getpid();//获得发送进程的id
if((msgkey=msgget(key,IPC_CREAT|0660))<0)
{
fprintf(stderr,"msgget error %s\n",strerror(errno));
exit(1);
}
printf("msgget key %d\n",msgkey);
fflush(stdout);
while(1)
{
count++;
bzero(&wmsg,sizeof(wmsg));
wmsg.mtype=10; //消息的类型
wmsg.count=count;
wmsg.from=pid;
strcpy(wmsg.mtext,"hello,i am coming");
if(msgsnd(msgkey,&wmsg,sizeof(wmsg.mtext),MSG_NOERROR)<0)
{
fprintf(stderr,"msgsnd error %s\n",strerror(errno));
}
sleep(2);
}
if((msgctl(msgkey,IPC_RMID,NULL))<0){
perror("msgctl");
exit(1);
}
return 0;
}
mesg_que_recv.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
key_t key;
pid_t pid;
int msgkey;
struct msgbuf{
int mtype;
pid_t from;
int count;
char mtext[50];
}rmsg;//消息的格式应该是一样的
pid=getpid();
key=ftok("/home/yandongsheng/",10);
while(1)
{
bzero(&rmsg,sizeof(rmsg));
if(msgrcv(msgkey,&rmsg,sizeof(rmsg.mtext),0,MSG_NOERROR)<0)
{
perror("msgrcv error");
}
printf("rmsg.from=%d\nmy pid is:",rmsg.from,pid);
printf("rmsg.mtype=%d\nrmsg.count=%d\nrmsg.mtext=%s\n",rmsg.mtype,rmsg.count,rmsg.mtext);
sleep(2);
}
if((msgctl(msgkey,IPC_RMID,NULL))<0){
perror("msgctl");
exit(1);
}
return 0;
}
先运行mesg_que_send.c 后运行mesg_que_recv.c 仅做演示
消息队列的实现包括创建和打开队列、添加消息、读取消息和控制消息队列这四种操作。
msgget:创建和打开队列,其消息数量受系统限制。
msgsnd:添加消息,将消息添加到消息队列尾部。
msgrcv:读取消息,从消息队列中取走消息。
msgctl:控制消息队列。
int msgget (key_t key, int flag)
key:返回新的或已有队列的ID,IPC_PRIVATE
int msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int flag)
其中:msqid是消息队列的队列ID;
msgp是消息内容所在的缓冲区;
msgsz是消息的大小;
msgflg是标志,IPC_NOWAIT若消息并没有立即发送而调用进程会立即返回。
int msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,long msgtyp, int flag)
msqid是消息队列的引用标识符;
msgp是接收到的消息将要存放的缓冲区;
msgsz是消息的大小;
msgtyp是期望接收的消息类型;
int msgctl (int msqid, int cmd, struct msqid_ds *buf)
msqid是消息队列的引用标识符;
cmd是执行命令;
buf是一个缓冲区。
cmd参数指定对于由msqid规定的队列要执行的命令:
IPC_STAT 取此队列的msqid_ds结构,并将其存放在buf指向的结构中。
IPC_SET 按由buf指向的结构中的值,设置与此队列相关的结构中的下列四个字段:
msg_perm.uid、msg_perm.gid、msg_perm;mode和msg_qbytes。此命令只能由下列两种进程执行:一种是其有效 用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。只有超级用户才能增加msg_qbytes的值。
IPC_RMID 从系统中删除该消息队列以及仍在该队列上的所有数据。这种删除立即生效。仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将出错返回 EIDRM。
此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。
msgflg是标志。
具体看例子:
mesg_que_send.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
key_t key;
int msgkey;
pid_t pid;
int count=0;
struct msgbuf{
int mtype;
pid_t from;
int count;
char mtext[50];
}wmsg;
key=ftok("/home/yandongsheng/",10);
pid=getpid();//获得发送进程的id
if((msgkey=msgget(key,IPC_CREAT|0660))<0)
{
fprintf(stderr,"msgget error %s\n",strerror(errno));
exit(1);
}
printf("msgget key %d\n",msgkey);
fflush(stdout);
while(1)
{
count++;
bzero(&wmsg,sizeof(wmsg));
wmsg.mtype=10; //消息的类型
wmsg.count=count;
wmsg.from=pid;
strcpy(wmsg.mtext,"hello,i am coming");
if(msgsnd(msgkey,&wmsg,sizeof(wmsg.mtext),MSG_NOERROR)<0)
{
fprintf(stderr,"msgsnd error %s\n",strerror(errno));
}
sleep(2);
}
if((msgctl(msgkey,IPC_RMID,NULL))<0){
perror("msgctl");
exit(1);
}
return 0;
}
mesg_que_recv.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
key_t key;
pid_t pid;
int msgkey;
struct msgbuf{
int mtype;
pid_t from;
int count;
char mtext[50];
}rmsg;//消息的格式应该是一样的
pid=getpid();
key=ftok("/home/yandongsheng/",10);
while(1)
{
bzero(&rmsg,sizeof(rmsg));
if(msgrcv(msgkey,&rmsg,sizeof(rmsg.mtext),0,MSG_NOERROR)<0)
{
perror("msgrcv error");
}
printf("rmsg.from=%d\nmy pid is:",rmsg.from,pid);
printf("rmsg.mtype=%d\nrmsg.count=%d\nrmsg.mtext=%s\n",rmsg.mtype,rmsg.count,rmsg.mtext);
sleep(2);
}
if((msgctl(msgkey,IPC_RMID,NULL))<0){
perror("msgctl");
exit(1);
}
return 0;
}
先运行mesg_que_send.c 后运行mesg_que_recv.c 仅做演示