2. Linux 源代码分析报告
Linux 源代码分析 ----ipc/msg.c
前言:
在操作系统中, 有些进程存在着相互制约的关系,这些
制约关系来源于并行进程的相互合作和资源共享。为了使合
作进程和资源共享进程能协调一致的向前推进,必须使他
们保持联系,一边相互了解。进程相互间需要交换一定数量
的信息, 以便协调一致共同完成指定的任务. 这种机制就叫
做进程间通信,或 IP C . 在 linux 中支持 UNIX S Y S T EM V
的三种通信机制 : 消息队列 , 信号量和共享内存 . 现就消息
队列这种机制进行分析.
包含的头文件:
#include <linux/malloc.h>
#include <linux/msg.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/uaccess.h>
m s g . c 中包含的函数模块:
Page2
4. Linux 源代码分析报告
从而访问 通信资源. Key 为 pu bli c , 则任何进程都可以
通过 key 得到引用标识.
2. struct msg
{
struct msg *msg_next; //消息队列中的下一个
long msg_type; //消息的类型
char *msg_spot; //存放消息内容的地址
time_t msg_time; //消息发送的时间
short msg_ts; //消息的长度
};
m s g 结构用来存放消息的有关信息.
3. struct msqid_ds
{
struct ipc_perm msg_perm;
struct msg *msg_first; //指向消息队列的第一条消息
struct msg *msg_last; //指向消息队列的最后一条消息
time_t msg_stime; // 最后发送时间
time_t msg_rtime; //最后接收时间
time_t msg_ctime; //最后修改时间
struct wait_queue *wwait; //写消息进程的等待队列
struct wait_queue *rwait; //读消息进程的等待队列
ushort msg_cbytes; //队列中消息的字节数
ushort msg_qnum; //队列中的消息数
ushort msg_qbytes; //队列中消息的最大字节数
ushort msg_lspid; // 最后一个发送消息的进程的标识号
Page4
5. Linux 源代码分析报告
ushort msg_lrpid; //最后一个接收消息的进程的标识号
};
每一个 m s qid_d s 结构代表一个消息队列, 是进
程读写的信息的存储空间。
static struct msqid_ds *msgque[MSGMNI];
定义了一个消息队列数组 m s g q u e , 数组的元素类
型是指向 m s qid_d s 结构的指针。消息在队列中是按
到来的顺序维护。进程读消息时,这些消息按 FIFO
从队列中移去。
msgque msgid_ds msg msg
msg_perms msg_next msg_next
msg_first msg_type
msg_last msg_spot
msg_stime
msg_ts
message
图: Linux 消息队列
以下是消息传递的示意图:
Page5
6. Linux 源代码分析报告
Struct msgqid_ds
receiver sender
msg msg msg
receiver
sender
4. struct msgbuf
{
long mtype; //消息的类型
char mtext[1]; //消息的内容
};
存放消息的信息。
5. struct wait_queue
{
struct wait_queue *next; //指针指向等待队列的下一个
struct task_struct *task;
/*task_struct 存放的是进程控制块的信息 */
};
wait_queu e 代表各种各样的进程等待队列。
初始化变量:
static int msgbytes = 0; //代表消息的字节数
static int msghdrs = 0;
static unsigned short msg_seq = 0; //代表消息的序列号
static int used_queues = 0; //代表使用的消息数
Page6
7. Linux 源代码分析报告
static int max_msqid = 0; //代表最大的消息序列号
static struct wait_queue *msg_lock = NULL;
函数列表:
1. void msg_init(void)
2. static int real_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int
msgflg)
3. static int real_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz,
long msgtyp, int msgflg)
4. asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp, size_t
msgsz, int msgflg)
5. asmlinkage int sys_msgrcv(int msqid, struct msgbuf *msgp, size_t
msgsz,
6. static int findkey(key_t key)
7. static int newque (key_t key, int msgflg)
8. asmlinkage int sys_msgget(key_t key, int msgflg)
9. static void free_que (int id)
10. asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
函数模块的说明与分析:
1. 初始化模块:
void __init msg_init (void)
函数参数:无
函数返回类型:空
函数功能:对消息队列及各变量初始化
{
int id;
for (id = 0; id < MSGMNI; id++)
msgque [id] = (struct msqid_ds *) IPC_UNUSED;
/* 给 指 向 消 息 队 列 的 指 针 分 配 空 间 , 标 志 为 IPC_UNUSED, 定
义见
linux/ipc.h : #define IPC_UNUSED ((void ) -1)*/
msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0;
msg_lock = NULL;
return;
}
2. 发送消息模块:
Page7