云文档网 - 专业文章范例文档资料分享平台

Linux的消息函数的分析

来源:网络收集 时间:2024-05-02 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xuecool-com或QQ:370150219 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

攀枝花学院本科学生课程设计任务书

题 目 1、课程设计的目的 ①、设计目的 a、通过对Linux的消息传递代码的分析, 了解Linux操作系统中用于消息传递的msgget、msgsnd、msgrcv、msgctl的执行过程, 锻炼学生分析大型软件代码的能力。 b、通过与同组同学的合作, 锻炼学生的合作能力。 2、课程设计的内容和要求(包括原始数据、技术要求、工作要求等) ②、设计内容 a、根据课程设计指导书提供的基础知识和有关资料, 分析相关代码, 得到相关的框图, 写出设计报告。 ③、设计要求 a、认真阅读代码,与同组同学合作,通过充分的讨论得到相关的结论。 ④、运行结果 a、分析系统源代码,得到相关框图。 3、主要参考文献与网址 [1] 计算机操作系统(第三版),汤小丹等,西安电子科技大学出版社, 2007年5月 [2] 操作系统习题解答与实验指导,王煜、张明、刘振鹏 ,高等教育出版社, 2004年12月 [3] 操作系统原理实验,周苏、金海溶、李洁、科学出版社, 2003年12月 [4] 操作系统教程题解与实验指导,孟静,高等教育出版社, 2002年6月 [5] 操作系统教程——原理和实例分析,孟静,高等教育出版社, 2001年9月 [6] VC++深入详解,孙鑫、余安萍,电子工业出版社,2006年 [7] VC++程序设计解析与训练,祁云嵩,华东理工大学出版社,2005年 [8] 谭浩强,张基温.C/C++程序设计教程[M].北京:高等教育出版社.2002年 [9] Jay Hilyard等著,C#经典实例.第2版,中国电力出版社,2007年6月 [10] [美]Karli Watson Christian Nagel等.C#入门经典(第3版).北京:清华大学出版 项目四:Linux的消息函数的分析 4、课程设计工作进度计划 序号 时间(天) 1 1天 内容安排 设计动员,布置任务,选题,查阅资料。 备注 2 3 4 5 总计 1天 1天 1天 1天 5天 需求分析与概要设计、详细设计。 编程,调试,单元测试。 完成模块联调,进行集成测试 成果验收,完成设计报告 日期 年 月 日 指导教师(签字) 教研室意见: 年 月 日 学生(签字): 接受任务时间: 年 月 日 注:任务书由指导教师填写。

课程设计(论文)指导教师成绩评定表

题目名称 评分项目 工作 表现 20% 01 02 03 04 05 06 07 08 学习态度 科学实践、调研 课题工作量 综合运用知识的能力 应用文献的能力 设计(实验)能力,方案的设计能力 计算及计算机应用能力 对计算或实验结果的分析能力(综合分析能力、技术经济分析能力) 插图(或图纸)质量、篇幅、设计(论文)规范化程度 设计说明书(论文)质量 创新 Linux的消息函数的分析 分值 6 7 7 10 5 5 5 10 得分 评价内涵 遵守各项纪律,工作刻苦努力,具有良好的科学工作态度。 通过实验、试验、查阅文献、深入生产实践等渠道获取与课程设计有关的材料。 按期圆满完成规定的任务,工作量饱满。 能运用所学知识和技能去发现与解决实际问题,能正确处理实验数据,能对课题进行理论分析,得出有价值的结论。 能独立查阅相关文献和从事其他调研;能提出并较好地论述课题的实施方案;有收集、加工各种信息及获取新知识的能力。 能正确设计实验方案,独立进行装置安装、调试、操作等实验工作,数据正确、可靠;研究思路清晰、完整。 具有较强的数据运算与处理能力;能运用计算机进行资料搜集、加工、处理和辅助设计等。 具有较强的数据收集、分析、处理、综合的能力。 能力 水平 35% 成果 质量 45% 09 10 11 5 30 10 符合本专业相关规范或规定要求;规范化符合本文件第五条要求。 综述简练完整,有见解;立论正确,论述充分,结论严谨合理;实验正确,分析处理科学。 对前人工作有改进或突破,或有独特见解。 成绩 指导教师评语 指导教师签名: 年 月 日

摘 要

Linux是一种自由和开放源码的类Unix操作系统。目前存在着许多不同

的Linux,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,从手机、平板电脑、路由器和视频游戏控制台,到台式计算机、大型机和超级计算机。

Linux采用消息队列的方式来实现消息传递。System V的消息队列

(message queues)是进程之间互相发送消息的一种异步(asynchronously)方式,在这种情形之下,发送方不必等待接收方检查它的消息——即在发送完消息后,发送方就可以从事其它工作了——而接收方也不必一直等待消息。

新的消息总是放在队列的末尾,接收的时候并不总是从头来接收,可以从

中间来接收。消息队列允许一个或多个进程写消息,一个或多个进程读取消息。Linux维护了一系列消息队列的msgque向量表。其中的每一个单元都指向一个msqid_ds的数据结构,完整描述这个消息队列。当创建消息队列的时候,从系统内存中分配一个新的msqid_ds的数据结构并插入到向量表中。

关键字 Linux , 消息函数 ,分析

目 录

摘 要 ........................................................................................................................... 4 1 课设简介 .................................................................................................................... 6

1.1课程设计题目 ..................................................................................................... 6 1.2课程设计小组成员 .............................................................................................. 6 1.3小组成员任务分配情况及每人所占工作比例 ........................................................ 6 2 LINUX的消息函数主模块功能描述............................................................................... 6 3 LINUX的消息函数各个子模块功能描述........................................................................ 7

3.1 Msgget:(李锐 负责)....................................................................................... 7 3.2 Msgsnd:(周健 负责) ..................................................................................... 8 3.3 Msgrcv:( 负责) ............................................................................................ 9 3.4 Msgctl:(周健 负责)..................................................................................... 10 4 LINUX的消息函数各个子模块相关函数代码分析结果..................................................11

4.1 有关常量及相关错误信息的含义:( 负责) ......................................................11

4.1.1 常量含义: ...........................................................................................11 4.1.2 错误信息含义 .......................................................................................11 4.2 函数sys_msgget的分析 (李锐 负责) .......................................................... 12 4.2.1 代码及注释 .......................................................................................... 12 4.3发送消息函数real_msgsnd的分析 (周健 负责) ............................................... 14 4.3.1代码分析 ................................................................................................ 14 4.4接收消息函数real_msgrcv的分析 ( 负责) .................................................... 18

4.4.1代码及注释 ............................................................................................ 18 4.5 函数sys_msgctl的分析 (李锐 负责) .......................................................... 23 4.5.1 代码及注释 .......................................................................................... 23

心得体会........................................................................................................................ 30 参考文献........................................................................................................................ 31

1 课设简介

1.1课程设计题目

LINUX的消息函数的分析

1.2课程设计小组成员

, ,李锐

1.3小组成员任务分配情况及每人所占工作比例

周健负责:分析消息队列的控制函数(sys_msgctl)以及与它相关的函数freeque,写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例25%。

周键负责:分析消息的发送函数(real_msgsnd)以及与它相关的函数sys_msgsnd,写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例25%。

负责:分析消息的接收函数(real_msgrcv)以及与它相关的函数sys_msgrcv,写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例25%。

李锐负责:分析消息队列的创建函数(sys_msgget)以及与它相关的函数newque、findkey、msg_init,写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。明确组内成员的明细分工,总体把握组内成员的进度。后期组织组内成员成果汇总进行本组总体报告撰写。所占工作比例25%。

2 LINUX的消息函数主模块功能描述

Linux采用消息队列的方式来实现消息传递。System V的消息队列(message queues)是进程之间互相发送消息的一种异步(asynchronously)方式,在这种情形之下,发送方不必等待接收方检查它的消息——即在发送完消息后,发送方就可以从事其它工作了——而接收方也不必一直等待消息。

新的消息总是放在队列的末尾,接收的时候并不总是从头来接收,可以从中间来接收。消息队列允许一个或多个进程写消息,一个或多个进程读取消息。Linux维护了一系列消息队列的msgque向量表。其中的每一个单元都指向一个msqid_ds的数据结构,完整描述这个消息队列。当创建消息队列的时候,从系统内存中分配一个新的msqid_ds的数据结构并插入到向量表中。

每一个msqid_ds数据结构都包括一个ipc_perm的数据结构和进入这个队列的消息的指针。另外,Linux保留队列的改动时间,例如上次队列写的时间等。Msqid_ds队列也包括两个等待队列:一个用于向消息队列写,另一个用于读。

每一次一个进程试图向写队列写消息,它的有效用户和组的标识符就要和队列的 ipc_perm数据结构的模式比较。如果进程可以向这个队列写,则消息会从进程的地址空间写到msg数据结构,放到消息队列的最后。每一个消息都带有进程间约定的,应用程序指定类型的标记。但是,因为Linux限制了可以写的消息的数量和长度,可能会没有空间容纳消息。这时,进程会被放到消息队列的写等待队列,然后调用调度程序选择一个新的进程运行。当一个或多个消息从这个消息队列中读出去的时候会被唤醒。

从队列中读是一个相似的过程。进程的访问权限一样被检查。一个读进程可以选择是不管消息的类型从队列中读取第一条消息还是选择特殊类型的消息。如果没有符合条件的消息,读进程会被加到消息队列的读等待进程,然后运行调度程序。当一个新的消息写到队列的时候,这个进程会被唤醒,继续运行。

3 LINUX的消息函数各个子模块功能描述

3.1 Msgget:(李锐 负责)

功能:取得一个消息队列。调用者提供消息队列的键标(用于表示一个消息

队列的唯一的名字),当这个队列存在的时候,这个系统调用负责返回这个队列的标识号;如果这个队列不存在,就创立一个消息队列,然后返回这个消息队列的标识号。主要由sys_msgget执行。 说明:系统调用返回与参数key相关的消息队列的标识符.

若以下事实成立,则与消息队列相关的标识符和数据结构将被创建出来:

. 若参数key等于IPC_PRIVATE.

. 若参数key没有存在的消息队列标识符与之相关,同时(msgflg&IPC_CREAT)为真.

创建消息队列的同时,与新的消息队列标识符相关的数据结构将被初始化为如下:

. msg_perm.cuid和msg_perm.uid设置为调用进程的有效UID. . msg_perm.cgid和msg_perm.gid设置为调用进程的有效GID. . msg_perm.mode访问权限比特位设置为msgflg访问权限比特位. . msg_qnum,msg_lspid,msg_lrpid,msg_stime,msg_rtime设置为0. . msg_ctime设置为当前系统时间. . msg_qbytes设置为系统允许的最大值.

返回值:调用成功则返回一个非0值,称为消息队列标识符;否则返回值为-1.

3.2 Msgsnd:(周健 负责)

功能:发送消息到指定的消息队列中。主要由real_msgsnd执行。 说明:发送一个消息到由msqid指定消息队列标识号的消息队列. 参数msgp指向一个用户定义的缓冲区,并且缓冲区的第一个域应为长

整型,指定消息类型,其他数据放在缓冲区的消息中其他正文区内. 下面是消息元素定义:

long mtype; char mtext[];

mtype是一个整数,用于接收进程选择消息类型.

mtext是一个长度为msgsz字节的任何正文,参数msgsz可从0

到系统允许的最大值之间变化.

msgflg指定操作行为:

. 若(msgflg&IPC_NOWAIT)是真的,消息并不是被立即发送而调用进程会立即返回.

. 若(msgflg&IPC_NOWAIT)不是真的,则调用进程会被挂起直到下面情况之一发生:

. 消息被发送出去.

. 消息队列标志被系统删除.系统调用返回-1.

. 调用进程接收到未被忽略的中断信号,调用进程继续执行或被终止.

调用成功后,对应指定的消息队列的相关结构做如下动作: . 消息数(msg_qnum)加1.

. 消息队列最近发送进程号(msg_lspid)改为调用进程号. . 消息队列发送时间(msg_stime)改为当前系统时间. 以上信息可用命令ipcs -a看到. 返回值:发送成功则返回0,否则返回-1.

3.3 Msgrcv:( 负责)

功能:用msgrcv函数系统调用从msqid消息队列中读取一条信息并将其放

入消息段指针msgp指向的结构。msgsz给出mtext的字节数, 如果所接收的消息比msgsz大且msgflg&MSG_NOERROR为真,则按msgsz的大小截断而不通知调用进程。从消息队列中取得指定类型的消息.。 说明:系统调用从由msqid指定的消息队列中读取一个由msgtyp指定类型

的消息到由msgp指向的缓冲区中,同样的,该缓冲区的结构如前所述,包括消息类型和消息正文.msgsz为可接收的消息正文的字节数.若接收到的消息正文的长度大于msgsz,则会被截短到msgsz字节为止(当消息标志msgflg&MSG_NOERROR为真时),截掉的部份将被丢失,而且不通知消息发送进程. msgtyp指定消息类型:

. 为0则接收消息队列中第一个消息.

. 大于0则接收消息队列中第一个类型为msgtyp的消息.

. 小于0则接收消息队列中第一个类型值不小于msgtyp绝对值且类

型值又最小的消息. msgflg指定操作行为:

. 若(msgflg&IPC_NOWAIT)是真的,调用进程会立即返回,若没有接收

到消息则返回值为-1,error设置为ENOMSG.

. 若(msgflg&IPC_NOWAIT)不是真的,则调用进程会被挂起直到下面情况之一发生:

. 队列中的消息的类型是有效的.

. 消息队列标志被系统删除.系统调用返回-1.

. 调用进程接收到未被忽略的中断信号,调用进程继续执行或被终止.

调用成功后,对应指定的消息队列的相关结构做如下动作: . 消息数(msg_qnum)减1.

. 消息队列最近接收进程号(msg_lrpid)改为调用进程号. . 消息队列接收时间(msg_rtime)改为当前系统时间. 以上信息可用命令ipcs -a看到.

返回值:调用成功则返回值等于接收到实际消息正文的字节数.不成功则返回-1.

3.4 Msgctl:(周健 负责)

功能:在消息队列上执行指定的操作。根据参数的不同和权限的不同,可以

执行检索、删除等等操作。主要由sys_msgctl执行。

说明:系统调用提供一系列消息控制操作,操作动作由cmd定义,以下cmd定

义值表明了各操作动作的定义.

. IPC_STAT:将msqid相关的数据结构中各个元素的当前值放入由buf指向的结构中.

. IPC_SET:将msqid相关的数据结构中的下列各元素设置为由buf指

向的结构中的对应值. msg_perm.uid msg_perm.gid msg_perm.mode msg_qbytes

该命令只能由有效UID等于msg_perm.cuid或msg_perm.uid的进程或有效UID有合适权限的进程操作.

只有具有合适权限的用户才能增加msg_qbytes的值.

. IPC_RMID:删除由msqid指示的消息队列.将它从系统中删除并破坏相关的数据结构.

该命令只能由有效UID等于msg_perm.cuid或msg_perm.uid的进程或

有效UID有合适权限的进程操作. 返回值:调用成功则返回值为0,否则为-1.

4 LINUX的消息函数各个子模块相关函数代码分析结果

4.1 有关常量及相关错误信息的含义:( 负责)

4.1.1 常量含义:

static struct msqid_ds *msgque[MSGMNI]; //消息队列 static int msgbytes = 0; //消息队列中所有消息的总字节数 static int msghdrs = 0; //消息队列的队头 static unsigned short msg_seq = 0;

static int used_queues = 0; //已用的消息队列数 static int max_msqid = 0; //消息队列最大的ID值

static struct wait_queue *msg_lock = NULL; //消息队列锁定,不让等待进程进入

4.1.2 错误信息含义

EINVAL EFAULT EIDRM EACCES EAGAIN

22 /* Invalid argument */ 14 /* Bad address */ 43 /* Identifier removed */ 13 /* Permission denied */ 11 /* Try again */

EINTR 4 /* Interrupted system call */

ENOMEM 12 /* Out of memory */ E2BIG

7 /* Arg list too long */

ENOMSG 42 /* No message of desired type */ ENOSPC

28 /* No space left on device */

ENOMEM 12 /* Out of memory */ EPERM ENOENT EEXIST

1 /* Operation not permitted */ 2 /* No such file or directory */ 17 /* File exists */

4.2 函数sys_msgget的分析 (李锐 负责)

4.2.1 代码及注释

asmlinkage int sys_msgget (key_t key, int msgflg) { int id, ret = -EPERM;

struct msqid_ds *msq; lock_kernel(); //锁内核

if (key == IPC_PRIVATE) //判断调用的参数key中是否指定了IPC_PRIVATE

即判断调用者需要一个新队列;

ret = newque(key, msgflg); //如果调用的参数key中指定了

IPC_PRIVATE则调用newque函数新建一个队列,并返回新建队列的序列号ID

else if ((id = findkey (key)) == -1) { //如果调用的参数key中没有

指定IPC_PRIVATE,则调用findkey函数来搜索一下是否有这个键值指定的队列,并用把函数的返回值赋给参数ID

if (!(msgflg & IPC_CREAT)) //如果key键值未被使用,则判断调用的

参数msgflg中是否设置了IPC_CREAT(00001000)位

ret = -ENOENT; //如果调用的参数msgflg中设置了

IPC_CREAT(00001000)位,则返回错误,错误类型ENOENT(No such file or directory)

else

ret = newque(key, msgflg); //如果调用的参数msgflg中没有设

置IPC_CREAT(00001000)位,则调用newque函数新建一个队列,并返回新建队列的序列号ID

} else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) { //key这个键

值已被使用。判断调用的参数msgflg是否标志了IPC_CREAT(00001000)位和IPC_EXCL(00002000)位

ret = -EEXIST; //如果调用的参数msgflg中既设置了

IPC_CREAT(00001000)位,又设置了IPC_EXCL(00002000)位,则返回错误,错误类型EEXIST(File exists)

} else { //如果有key这个键值指定的队列,则使用这个键值所指明的队

列作为当前消息队列

msq = msgque[id]; //把用findkey返回的这个键值所指明的队列指针

赋给当前消息队列

if (msq == IPC_UNUSED || msq == IPC_NOID) //判断当前消息队列

(msgque)项目是否被设置IPC_UNUSED或IPC_NOID

ret = -EIDRM; //如果当前消息队列(msgque)项目指向被设置

IPC_UNUSED或被设置IPC_NOID,则该地方没有消息队列(msgque)或者调用者缺少访问它的权限返回错误,错误类型EACCES(Identifier removed)

else if (ipcperms(&msq->msg_perm, msgflg)) //如果当前消息队列指

针指既没有向IPC_UNUSED又没有指向IPC_NOID,判断是否允许访问进程间通讯资源IPC

ret = -EACCES; //如果返回值非0,则不允许访问进程间通讯资源

IPC,返回错误,错误类型EACCES(Permission denied)

else

ret = (unsigned int) msq->msg_perm.seq * MSGMNI + id; //如

果返回值ID为0,则允许访问进程间通讯资源IPC,序列编号和msgque下标被编码在返回值里。这个编号将成为调用者要传递给sys_msgsnd、sys_msgrcv,以及sys_msgctl的msgid参数。

}

}

unlock_kernel();//释放内核 return ret; //返回ret值

4.3发送消息函数real_msgsnd的分析 (周健 负责)

4.3.1代码分析

static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) //实现sys_msgsnd的实质内容

{ int id;

if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0) //一系列条struct msqid_ds *msq;

struct ipc_perm *ipcp; //访问权限控制结构 struct msg *msgh; long mtype;

件判断消息的大小是否超过消息的最大值

return -EINVAL; //如果消息的大小超过消息的最大值,

//则返回错误,错误类型EINVAL(Invalid argument)

if (get_user(mtype, &msgp->mtype))

return –EFAULT(Bad address);

if (mtype < 1) //判断消息的类型是否合法

return -EINVAL; //如果消息的类型不合法,

//则返回错误,错误类型EINVAL(Invalid argument) 给ID

id = (unsigned int) msqid % MSGMNI; //把消息队列的数组下标值赋

msq = msgque [id]; //在消息队列中找到要发送的消息队列

if (msq == IPC_UNUSED || msq == IPC_NOID) //判断当前待发送的消

息队列(msgque)项目是否被设置IPC_UNUSED或IPC_NOID

return -EINVAL; //如果当前待发送的消息队列(msgque)项目被设

置了IPC_UNUSED或IPC_NOID,则该消息队列(msgque)不存在返回错误,错误类型EINVAL(Invalid argument)

slept:

if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) //判断ipcp = &msq->msg_perm; //对IPC进行赋值,进程间通讯权限允许

保存在消息队列中的序列号是否和那个msgque参数里的编码相匹配

return -EIDRM; //如果保存在消息队列中的序列号不和那个

msgque参数里的编码相匹配,则返回错误,错误类型EIDRM(Identifier removed)

return -EACCES; //如果调用者没有写消息的权限,则返回错误,if (ipcperms(ipcp, S_IWUGO)) //判断调用者是否拥有写消息队列的权

错误类型EACCES(Permission denied)

if (msgsz + msq->msg_cbytes > msq->msg_qbytes) //检查如果提供的

消息被写入队列之后是否会超过队列所允许的最大容量

{

if (msgsz + msq->msg_cbytes > msq->msg_qbytes) //检查如果提

供的消息被写入队列之后是否会超过队列所允许的最大容量

{

if (msgflg & IPC_NOWAIT) //队列中没有空间。判断msgflg

里的IPC_NOWAIT位是否被设置了

return -EAGAIN; //msgflg里的IPC_WAIT位被设置了,调

用者不用等待,返回错误,错误类型EAGAIN(Try again)

if (signal_pending(current)) //调用signal_pending使进程

进入休眠状态。首先判断是否有信号正在等待该进程

return -EINTR; //如果存在正在等待消息,就会用进程的

休眠被信号中断的方式来处理它,返回错误,错误类型EINTR(Interrupted system call)

interruptible_sleep_on (&msq->wwait); //如果没有正在等待

进程的信号,进程就进入休眠状态,直到有信号到达或一条消息移出队列时才被唤醒

}

msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_KERNEL);

}

goto slept; //当进程被唤醒之后,它将再次向队列写入

//调用kmalloc函数为消息队列头(struct msg)和消息体分配足够的空间,消息体将紧接在消息头后面存发。消息头的msg_spot直接指向该头部之后消息体开始的地发

if (!msgh) //判断是否分配成功

return -ENOMEM; //如果分配失败,返回错误,错误类型ENOMEM(Out

of memory)超出内存界限

if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz)) //调用msgh->msg_spot = (char *) (msgh + 1);

copy_from_user函数从用户空间复制消息体

{ kfree(msgh); //调用kfree函数释放掉msgh的空间

return -EFAULT; //从用户空间复制消息体失败,

//返回错误,错误类型EFAULT(Bad address)

}

if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID

|| msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) //检

查消息队列的合法性

{

kfree(msgh); //调用kfree函数释放掉msgh的空间

return -EIDRM; //从用户空间复制消息体失败,

//返回错误,错误类型EIDRM(Identifier removed)

}

//填写消息头,并将其入队,并更新队列自己相应的统计值

msgh->msg_next = NULL; //对头的下一个指针赋空 msgh->msg_ts = msgsz; //消息的大小 msgh->msg_type = mtype; //消息的类型 msgh->msg_stime = CURRENT_TIME;

if (!msq->msg_first) //判断该消息队列是否就一个消息单元

msq->msg_first = msq->msg_last = msgh; //如果该消息队列中就

一个消息单元,则把指针msg_first与msg_last指向一块

else {

//如果消息消息队列不止一个消息单元,把当前消息单元添加到消息队列尾 msq->msg_last->msg_next = msgh;

msq->msg_cbytes += msgsz;

msgbytes += msgsz; //整个消息大小增加 msghdrs++;

msq->msg_qnum++; //消息队列数加1 msq->msg_lspid = current->pid; msq->msg_stime = CURRENT_TIME; }

msq->msg_last = msgh;

}

wake_up (&msq->rwait); //唤醒所有等待消息到达这个队列的进程

return 0; //返回0表示发送成功

4.4接收消息函数real_msgrcv的分析 ( 负责)

4.4.1代码及注释

static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)

{ //取消息函数,该函数为实际操作函数

struct msqid_ds *msq;

//每个消息队列占一个msqid_ds结构,include/linux/msg.h/ 结构体

id = (unsigned int) msqid % MSGMNI; if (msqid < 0 || (long) msgsz < 0)

return –EINVAL; //若消息长度值越界则返回错误信息 int id;

struct msg *nmsg = NULL; //存放消息内容的结构struct ipc_perm *ipcp; //访问权限控制结构 struct msg *tmsg, *leastp = NULL; //存放消息内容的

//MSGMNI为消息队列的最大长度,

//取模的作用是保证消息队列的个数不越界

msq = msgque [id]; //msgque []是为全局变量,为系统所能维

持的消息队列的

// 个数消息队列标识号对两段信息进行编码

if (msq == IPC_NOID || msq == IPC_UNUSED) //指针无效或者所分配

的地址被破坏

/ * find message of correct type. //寻找正确类型的消息 * msgtyp = 0 => get first. //取队列中第一个消息给nmsg. * msgtyp > 0 => get first message of matching type. //取队列

return –EINVAL; //则返回错误信息

ipcp = &msq->msg_perm; //将消息的控制信息赋值给ipcp

中第一个消息给nmsg.

* msgtyp < 0 => get message with least type must be < abs(msgtype). //取队列中msgtyp最小的消息给nmsg.

*/

while (!nmsg) {

if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) { }

if (ipcperms (ipcp, S_IRUGO)) { //判断该进程是否有权读取

return –EIDRM;

该消息队列

if (msgtyp == 0) //msgtyp为0时取队列中第一条消息

nmsg = msq->msg_first;

}

return –EACCES;

else if (msgtyp > 0) { //当msgtyp大于0时

if (msgflg & MSG_EXCEPT) {

//若标志字msgflg中设置了MSG_EXCEPT 则进行如下操

for (tmsg = msq->msg_first; tmsg;

tmsg = tmsg->msg_next) //初值为tmsg =

msq->msg_first,

//当tmsg不为NULL时循环,步进条件为tmsg = tmsg->msg_next

if (tmsg->msg_type != msgtyp) //当遇到消息类型不同于所要

break; //求类型时跳出循环

nmsg = tmsg; //上一段代码取出队

//列中第一条消息类型与所给类型不符合的消息。

} else {

for (tmsg = msq->msg_first; tmsg; tmsg = tmsg->msg_next)

if (tmsg->msg_type == msgtyp)

//取出该消息这一段代码的作用

//是取出队列中第一条消息类型与所给类型

相符的消息。

Break;

nmsg = tmsg;

}

else { //当msgtyp小于0时

for (leastp = tmsg = msq->msg_first; tmsg; //初始设置 tmsg = tmsg->msg_next) //leastp}

为消息队列头

if (tmsg->msg_type < leastp->msg_type)

参考文献

[1] 计算机操作系统(第三版),汤小丹等,西安电子科技大学出版社, 2007年5月

[2] 操作系统习题解答与实验指导,王煜、张明、刘振鹏 ,高等教育出版社, 2004年12月

[3] 操作系统原理实验,周苏、金海溶、李洁、科学出版社, 2003年12月 [4] 操作系统教程题解与实验指导,孟静,高等教育出版社, 2002年6月 [5] 操作系统教程——原理和实例分析,孟静,高等教育出版社, 2001年9月

[6] VC++深入详解,孙鑫、余安萍,电子工业出版社,2006年

[7] VC++程序设计解析与训练,祁云嵩,华东理工大学出版社,2005年 [8] 谭浩强,张基温.C/C++程序设计教程[M].北京:高等教育出版社.2002年

[9] Jay Hilyard等著,C#经典实例.第2版,中国电力出版社,2007年6月 [10]

[美]Karli Watson Christian Nagel等.C#入门经典(第3版).北京:

清华大学出版

百度搜索“yundocx”或“云文档网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,云文档网,提供经典综合文库Linux的消息函数的分析在线全文阅读。

Linux的消息函数的分析.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.yundocx.com/wenku/212939.html(转载请注明文章来源)
Copyright © 2018-2022 云文档网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:370150219 邮箱:370150219@qq.com
苏ICP备19068818号-2
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:7 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219