党卫队为什么设旗队长:LINUX消息队列一

来源:百度文库 编辑:偶看新闻 时间:2024/05/06 14:04:40
这节我们开始消息队列(也有称报文队列)的实践到内核,我是无名小卒,很多书上讲到的消息队列都很枯燥,我尽量写的易读易懂,避免书者之风,我们的目标是深入到内核的细节中去,从实践的应用上追踪到内核的实现。消息队列的概念相信大家能从字面上看的出,他的优点资料非常全面,不介绍了我们直接进入主题,看代码我们在实验中写二个程序一个是msg1.c是接受消息队列程序,另一个是msg2.c是发送消息队列用的,在这二个程序中可以创建新的消息队列,但是在接受的程序中在完成接受后我们删除消息队列。下面是msg1.c接受消息队列的程序代码:

#include
#include
#include
#include

#include
#include
#include

struct my_msg_st{
long int my_msg_type;
char some_text[BUFSIZ];
};
int main()
{
int running=1;
int msgid;
struct my_msg_st some_data;
long int msg_to_receive=0;

下面我们要建立一个消息队列,这个函数就是msgget()
msgid=msgget((key_t)1234,0666|IPC_CREAT);
if(msgid==-1){
fprintf(stderr,"msgget failed\n");
exit(EXIT_FAILURE);
}

while(running){
if(msgrcv(msgid,(void*)&some_data,BUFSIZ,msg_to_receive,0)==-1)fprintf(stderr,"msgrcv failed\n");
exit(EXIT_FAILURE);
}
上面的while循环中是通过msgrcv()函数从消息队列中接受消息直到没有消息为止,我们继续往下看
printf("you wrote: %s\n",some_data.some_text);
if(strncmp(some_data.some_text,"end",3)==0){
running=0;
}
}
if(msgctl(msgid,IPC_RMID,0)==-1){
fprintf(stderr,"msgctl failed \n");
exit(EXIT_FAILURE);
}
上面是通过msgctl()函数删除消息队列
exit(EXIT_SUCCESS);
}{



sys_ipc()函数的代码比较容易懂,从中我们也可以看出进程间通信的信号量还有共享内存也是通过个系统调用入口进入的,我们先不管其他的,重点看我们关于消息队列的部分,不言而喻,msgget()进入sys_ipc()时,肯定会走到这里

一、消息队列的建立

case MSGGET:
        return sys_msgget ((key_t) first, second);

至于上面的参数call是如何设置的,那应该是在C语言中的库函数时过渡到linux系统调用时自动设置好的,我们先不要关心这个过程,只要顺着内核进入抓关键,现在我们看到在这里调用了一个sys_msgget()函数,而这个函数的参数与上面msgget()的对照一下会发现完全相同的个数,我们追踪进入sys_msgget()去看一下,先列出这个函数,这个函数位于ipc/msg.c中第312行:

asmlinkage long sys_msgget(key_t key, int msgflg)
{
    struct ipc_namespace *ns;
    struct ipc_ops msg_ops;
    struct ipc_params msg_params;

     ns = current->nsproxy->ipc_ns;

     msg_ops.getnew = newque;
     msg_ops.associate = msg_security;
     msg_ops.more_checks = NULL;

     msg_params.key = key;
     msg_params.flg = msgflg;

    return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params);
}

我们先来看一下这二个参数,我建议朋友们在学习内核的函数时一定要注意函数的参数,包括他们的类型,还有就是函数的返回类型,这些对阅读内核源码非常必要,尤其是我们在追踪一个函数的调用过程时,参数更是环节中的纽带,第一个参数是key_t key,它是一个key_t类型,内核中定义它为int,但是我们从msgget()的参数界面上

msgget((key_t)1234,0666|IPC_CREAT);

第一个参数是转换为key_t类型,这是为了保持与进入sys_msgget()函数保持参数对正,我们可看出传递进来的key这个值是1234,在这里我们要强调一下,这个key的作用是为了区分消息队列(有的称为报文队列,以下我们统称消息队列)用的,朋友们都知道文件系统中的文件区分是用文件号来进行的,所以消息队列使用一个键值意义上等同于文件号,但是他并没有使用文件号。

第二个参数是int msgflg,类型是int,参数名称msgflg意为message flag,很清晰,代表着消息队列的一些标记设置,在这里我们看到传递进来的是0666|IPC_CREAT,采用的是八进制我们从上面的sys_msgget()中看到这二个函数使用在

msg_params.key = key;
msg_params.flg = msgflg;