ImageVerifierCode 换一换
格式:DOCX , 页数:34 ,大小:426.53KB ,
资源ID:6004478      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/6004478.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux的IPC消息实现机制分析及.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Linux的IPC消息实现机制分析及.docx

1、Linux的IPC消息实现机制分析及东北大学秦皇岛分校计算机与通信工程学院操作系统课程设计设计题目 Linux的IPC消息实现机制分析及进程管理器专业名称计算机科学与技术班级学号学生姓名指导教师王翠荣设计时间2015.01.052015.01.15课程设计任务书专业:计算机科学与技术 学号: 学生姓名(签名): 设计题目:Linux的IPC消息实现机制的分析一、设计实验条件综合楼808实验室二、设计任务及要求仔细阅读设计题目要求,对设计内容进行详细分析、设计。每组同学需有明确分工,并在提交的课程设计报告中能够充分体现具体分工情况,设计报告中体现个人分工部分的内容不应低于正文60%。报告内容应包

2、括题目分析、总体设计、代码实现(如果是内核分析题目此部分为内核主要代码和算法等的分析)、结果展示和课程设计总结几个组成部分。报告格式按照“计算机与通信工程学院课程设计模板”中的要求编写。三、 设计报告的内容1.设计题目分析与设计任务(设计任务书) 1.1设计题目:进程间通信(IPC)的一个主要通信方式是通过消息,通过对Linux内核进行分析,说明Linux用于消息实现的主要数据结构,以及实现的方法。 1.2设计任务分析:Linux采用消息队列的方式来实现消息传递。System V的消息队列(message queues)是进程之间互相发送消息的一种异步(asynchronously)方式,在这

3、种情形之下,发送方不必等待接收方检查它的消息即在发送完消息后,发送方就可以从事其它工作了而接收方也不必一直等待消息。新的消息总是放在队列的末尾,接收的时候并不总是从头来接收,可以从中间来接收。消息队列允许一个或多个进程写消息,一个或多个进程读取消息。Linux维护了一系列消息队列的msgque向量表。其中的每一个单元都指向一个msqid_ds的数据结构,完整描述这个消息队列。当创建消息队列的时候,从系统内存中分配一个新的msqid_ds的数据结构并插入到向量表中。每一个msqid_ds数据结构都包括一个ipc_perm的数据结构和进入这个队列的消息的指针。另外,Linux保留队列的改动时间,例

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

5、限一样被检查。一个读进程可以选择是不管消息的类型从队列中读取第一条消息还是选择特殊类型的消息。如果没有符合条件的消息,读进程会被加到消息队列的读等待进程,然后运行调度程序。当一个新的消息写到队列的时候,这个进程会被唤醒,继续运行。 1.3设计任务书:小组成员任务分配情况及每人所占工作比例小组成员:负责:分析消息队列的控制函数(sys_msgctl)以及与它相关的函数freeque,写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例25。负责:分析消息的发送函数(real_msgsnd)以及与它相关的函数sys_msgsnd,写出代码分析结果,并画出流程图来表示相关函数

6、之间的相互调用关系。所占工作比例25。负责:分析消息的接收函数(real_msgrcv)以及与它相关的函数sys_msgrcv,写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例25。负责:分析消息队列的创建函数(sys_msgget)以及与它相关的函数newque、findkey、msg_init,写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例25。2.前言(绪论)(设计的目的、意义等) 在操作系统中,有些进程存在着相互制约的关系,这些制约关系来源于并行进程的相互合作和资源共享。为了使合作进程和资源共享进程能协调一致的向前推进,必须使他

7、们保持联系,一边相互了解。进程相互间需要交换一定数量的信息,以便协调一致共同完成指定的任务. 这种机制就叫做进程间通信,或IPC.在linux 中支持UNIX SYSTEM V 的三种通信机制: 消息队列, 信号量和共享内存. 现就消息队列这种机制进行分析,以达到充分理解Linux内核代码及消息队列机制的具体实现过程中的数据结构及方法。3.LINUX的消息函数各个子模块分析3.1Msgrcv:(负责)功能:用msgrcv函数系统调用从msqid消息队列中读取一条信息并将其放入消息段指针msgp指向的结构。msgsz给出mtext的字节数, 如果所接收的消息比msgsz大且msgflg&MSG_

8、NOERROR为真,则按msgsz的大小截断而不通知调用进程。从消息队列中取得指定类型的消息.。说明:系统调用从由msqid指定的消息队列中读取一个由msgtyp指定类型的消息到由msgp指向的缓冲区中,同样的,该缓冲区的结构如前所述,包括消息类型和消息正文.msgsz为可接收的消息正文的字节数.若接收到的消息正文的长度大于msgsz,则会被截短到msgsz字节为止(当消息标志msgflg&MSG_NOERROR为真时),截掉的部份将被丢失,而且不通知消息发送进程.msgtyp指定消息类型: . 为0则接收消息队列中第一个消息. . 大于0则接收消息队列中第一个类型为msgtyp的消息. .

9、小于0则接收消息队列中第一个类型值不小于msgtyp绝对值且类型值又最小的消息. msgflg指定操作行为: . 若(msgflg&IPC_NOWAIT)是真的,调用进程会立即返回,若没有接收到消息则返回值为-1,error设置为ENOMSG. . 若(msgflg&IPC_NOWAIT)不是真的,则调用进程会被挂起直到下面情况之一发生: . 队列中的消息的类型是有效的. . 消息队列标志被系统删除.系统调用返回-1. . 调用进程接收到未被忽略的中断信号,调用进程继续执行或被终止. 调用成功后,对应指定的消息队列的相关结构做如下动作: . 消息数(msg_qnum)减1. . 消息队列最近接

10、收进程号(msg_lrpid)改为调用进程号. . 消息队列接收时间(msg_rtime)改为当前系统时间. 以上信息可用命令ipcs -a看到.返回值:调用成功则返回值等于接收到实际消息正文的字节数.不成功则返回-1.数据结构分析:图1 数据结构总体结构Struct msqid_ds:代表一个消息队列。它的成员如下:msg_perm:表明那个进程可以读写这个消息队列;msg_first:指向队列中第一个消息的指针;msg_last:指向队列中最后一个消息的指针;msg_stime:纪录消息被送入队列的最后时间;msg_rtime:纪录从队列中读出消息的最后时间;msg_ctime:上一次改变

11、队列的时间;(可以是队列创立的时间或者是上一次用msgctl系统调用来设置参数的时间。)wwait:等待进入消息队列的消息队列;rwait:如果在接收消息的时候没有可以接收的消息,那么根据这个设置来看是返回一个错误代码表示读消息失败还是阻塞等待消息到来;msg_cbytes:当前队列中消息的总字节数;msg_qnum:队列中消息的总数;msg_qbytes:队列中允许存储的消息的最大字节数;msg_lspid:最后消息发送方的PID;msg_lrpid:最后消息接收方的PID;有关常量及相关错误信息的含义:常量含义:static struct msqid_ds *msgqueMSGMNI; /

12、消息队列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; /消息队列锁定,不让等待进程进入错误信息含义:EINVAL 22 /* Invalid argument */EFAULT 14 /* Bad a

13、ddress */EIDRM 43 /* Identifier removed */EACCES 13 /* Permission denied */EAGAIN 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 me

14、mory */EPERM 1 /* Operation not permitted */ENOENT 2 /* No such file or directory */EEXIST 17 /* File exists */接收消息函数real_msgrcv的分析:代码及注释static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) /取消息函数,该函数为实际操作函数 struct msqid_ds *msq; /每个消息队列占一个msqid_ds结构,include

15、/linux/msg.h/ struct ipc_perm *ipcp; /访问权限控制结构 struct msg *tmsg, *leastp = NULL; /存放消息内容的结构体 struct msg *nmsg = NULL; /存放消息内容的结构体 int id; if (msqid 0 | (long) msgsz msg_perm; /将消息的控制信息赋值给ipcp / * find message of correct type. /寻找正确类型的消息 * msgtyp = 0 = get first. /取队列中第一个消息给nmsg. * msgtyp 0 = get fir

16、st message of matching type. /取队列中第一个消息给nmsg. * msgtyp get message with least type must be msg_perm.seq != (unsigned int) msqid / MSGMNI) return -EIDRM; if (ipcperms (ipcp, S_IRUGO) /判断该进程是否有权读取该消息队列 return -EACCES; if (msgtyp = 0) /msgtyp为0时取队列中第一条消息 nmsg = msq-msg_first; else if (msgtyp 0) /当msgty

17、p大于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 fo

18、r (tmsg = msq-msg_first; tmsg; tmsg = tmsg-msg_next) if (tmsg-msg_type = msgty /取出该消息这一段代码的作用 /是取出队列中第一条消息类型与所给类型相符的消息。 break; nmsg = tmsg; else /当msgtyp小于0时 for (leastp = tmsg = msq-msg_first; tmsg; /初始设置 tmsg = tmsg-msg_next) /leastp为消息队列头 if (tmsg-msg_type msg_type) /若当前消息的类型码小 /于leastp的类型码 least

19、p = tmsg; /将临时当前消息指针tmsg赋值给leastp if (leastp & leastp-msg_type = - msgtyp) /若leastp存在且其指向 /消息的类型码小于给定类型码的绝对值 nmsg = leastp; /将leastp赋值给当前指针nmsg if (nmsg) /* done finding a message */ /如果其中存在符合类型的消息 if (msgsz msg_ts) & !(msgflg & MSG_NOERROR) return -E2BIG; /若消息允许大小(msgsz)小于消息队列中特定消 /并且没有设置MSG_NOERRO

20、R则取消息失败 msgsz = (msgsz nmsg-msg_ts)? nmsg-msg_ts : msgsz; /在消息允许大小msgsz和消息队列中特定消息大小nmsg-msg_ts /取较大的值赋值给msgsz if (nmsg = msq-msg_first) /若所取消息为消息队列头 msq-msg_first = nmsg-msg_next; /则将nmsg-msg_next重新置为消息队列头 else /若所取消息不是消息队列头 for (tmsg = msq-msg_first; tmsg; tmsg = tmsg-msg_next) if (tmsg-msg_next =

21、nmsg) /循环搜索到要取消息的前一个指针tmsg break; tmsg-msg_next = nmsg-msg_next; /重新设置msg_next指针域 if (nmsg = msq-msg_last)/若所取消息是消息队列尾 msq-msg_last = tmsg; /重新设置msg_last指针域 if (!(-msq-msg_qnum) /若取出消息后队列中已无消息 msq-msg_last = msq-msg_first = NULL; /设队列首与队列尾为NULL msq-msg_rtime = CURRENT_TIME;/取消息时间更新为当前时间 msq-msg_lrpi

22、d = current-pid; /取消息进程号更新为当前进程号 msgbytes -= nmsg-msg_ts; /全局变量msgbytes用来统计使用的消息字节的大小 /减少相应的字节 msghdrs-; /全局变量msghdrs用来统计小心队列的个数,加1 msq-msg_cbytes -= nmsg-msg_ts; /队列中消息字节数减少 wake_up (&msq-wwait); /唤醒所有在该消息队列上等待的写消息进程 if (put_user (nmsg-msg_type, &msgp-mtype) | copy_to_user (msgp-mtext, nmsg-msg_spo

23、t, msgsz) /将消息赋值到用户空间 msgsz = -EFAULT; kfree(nmsg); /释放空间 return msgsz; /返回取得消息的大小 else /若没有找到符合消息类型的消息 if (msgflg & IPC_NOWAIT) /若设置IPC_NOWAIT return -ENOMSG; /则返回错误代码 if (signal_pending(current) /有信号要调用当前进程 return -EINTR; interruptible_sleep_on (&msq-rwait);/让该进程在读进程上阻塞 return -1; /返回-1表示接收失败图2 接收

24、消息的函数real_msgrcv流程图利用消息队列进行通信的实例: 发送端代码: #include#include#include#include#include#include #include struct msgbuf long type;char ptr0;int main(int argc,char *argv) key_t key;key=ftok(argv1,100); int msgid;msgid=msgget(key,IPC_CREAT|0600); pid_t pid;pid=fork(); if(pid=0) while(1) printf(please input m

25、sg to send:);char buf128;fgets(buf,128,stdin); struct msgbuf *ptr=malloc(sizeof(struct msgbuf)+strlen(buf)+1); ptr-type=1;memcpy(ptr-ptr,buf,strlen(buf)+1); msgsnd(msgid,ptr,strlen(buf)+1,0);free(ptr); else struct msgbuf long type;char ptr1024; ; while(1) struct msgbuf mybuf;memset(&mybuf,0,sizeof(m

26、ybuf); msgrcv(msgid,&mybuf,1024,2,0); printf(recv msg:%sn,mybuf.ptr); 接收端代码: #include#include#include#include#include#include #include struct msgbuf long type; char ptr0;int main(int argc,char *argv) key_t key; key=ftok(argv1,100); int msgid; msgid=msgget(key,IPC_CREAT|0600); pid_t pid; pid=fork();

27、if(pid=0) /send while(1) printf(please input msg to send:); char buf128; fgets(buf,128,stdin); struct msgbuf *ptr=malloc(sizeof(struct msgbuf)+strlen(buf)+1); ptr-type=2; /send msg type=2 memcpy(ptr-ptr,buf,strlen(buf)+1); msgsnd(msgid,ptr,strlen(buf)+1,0); free(ptr); else struct msgbuf long type; char ptr1024; ; while(1) struct msgbuf mybuf; memset(&mybuf,0,sizeof(mybuf); msgrcv(msgid,&mybuf,1024,1,0); /recv msg type=2 printf(recv msg:%sn,mybuf.ptr); 运行截图3.2Msgget:(负责)功能:取得一个消息队列。调用者提供消息队列

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1