![操作系统实验指导书_第1页](http://file1.renrendoc.com/fileroot_temp2/2020-7/21/5ee19cac-9e1d-4fd1-af3c-2ad0e3b28342/5ee19cac-9e1d-4fd1-af3c-2ad0e3b283421.gif)
![操作系统实验指导书_第2页](http://file1.renrendoc.com/fileroot_temp2/2020-7/21/5ee19cac-9e1d-4fd1-af3c-2ad0e3b28342/5ee19cac-9e1d-4fd1-af3c-2ad0e3b283422.gif)
![操作系统实验指导书_第3页](http://file1.renrendoc.com/fileroot_temp2/2020-7/21/5ee19cac-9e1d-4fd1-af3c-2ad0e3b28342/5ee19cac-9e1d-4fd1-af3c-2ad0e3b283423.gif)
![操作系统实验指导书_第4页](http://file1.renrendoc.com/fileroot_temp2/2020-7/21/5ee19cac-9e1d-4fd1-af3c-2ad0e3b28342/5ee19cac-9e1d-4fd1-af3c-2ad0e3b283424.gif)
![操作系统实验指导书_第5页](http://file1.renrendoc.com/fileroot_temp2/2020-7/21/5ee19cac-9e1d-4fd1-af3c-2ad0e3b28342/5ee19cac-9e1d-4fd1-af3c-2ad0e3b283425.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、操作系统实验指导书操作系统课程组编著计算机学院目 录前言- 1 -第一部分 实验环境及系统函数介绍- 2 -第二部分 实验内容- 6 -实验项目一 熟悉LINUX基本命令及编程环境- 6 -实验项目二 进程管理- 8 -实验项目三 进程调度- 13 -实验项目四 进程通信- 19 -实验项目五 存储管理- 28 -前言计算机操作系统是计算机科学与技术专业的主要专业基础课程,其实践性、应用性很强。实践教学环节是必不可少的一个重要环节。计算机操作系统的实验目的是加深对理论教学内容的理解和掌握,使学生较系统地掌握操作系统的基本原理,加深对操作系统基本方法的理解,加深对课堂知识的理解,为学生综合运用所
2、学知识,在Linux环境下调用一些常用的函数编写功能较简单的程序来实现操作系统的基本方法、并在实践应用方面打下一定基础。要求学生在实验指导教师的帮助下自行完成各个操作环节,并能实现且达到举一反三的目的,完成一个实验解决一类问题。要求学生能够全面、深入理解和熟练掌握所学内容,并能够用其分析、设计和解答类似问题;对此能够较好地理解和掌握,并且能够进行简单分析和判断;能够熟练使用Linux用户界面;掌握操作系统中进程的概念和控制方法;了解进程的并发,进程之间的通信方式,了解虚拟存储管理的基本思想。同时培养学生进行分析问题、解决问题的能力;培养学生完成实验分析、实验方法、实验操作与测试、实验过程的观察
3、、理解和归纳能力。为了收到良好的实验效果,编写了这本实验指导书。在指导书中,每一个实验均按照该课程实验大纲的要求编写,力求紧扣理论知识点、突出设计方法、明确设计思路,通过多种形式完成实验任务,最终引导学生有目的、有方向地完成实验任务,得出实验结果。任课教师在实验前对实验任务进行一定的分析和讲解,要求学生按照每一个实验的具体要求提前完成准备工作,如:查找资料、设计程序、完成程序、写出预习报告等,做到有准备地上机。进行实验时,指导教师应检查学生的预习情况,并对调试过程给予积极指导。实验完毕后,学生应根据实验数据及结果,完成实验报告,由学习委员统一收齐后交指导教师审阅评定。实验成绩考核:实验成绩占计
4、算机操作系统课程总评成绩的20%。指导教师每次实验对学生进行出勤考核,对实验效果作记录,并及时批改实验报告,综合评定每一次的实验成绩,在学期终了以平均成绩作为该生的实验成绩。有以下情形之一者,实验成绩为不及格:1. 迟到、早退、无故缺勤总共3次及以上者;2. 未按时完成实验达3次及以上者;3. 缺交实验报告2次及以上者。第一部分 实验环境及系统函数介绍DOS操作系统是单道操作系统,无法进行多道程序设计,Windows环境下的Visual C+虽然也可用于多道程序设计,但是并不是完全的多道,因为它也可用于DOS编程。所以我们的实验选用Linux操作系统。Linux操作系统是一个类UINX操作系统
5、,是一个纯多道并发的网络操作系统。1.1 Linux操作系统简介 Linux是一个多用户操作系统,是UNIX的一个克隆版本(界面相同但内部实现不同),同时它是一个自由软件,是免费的、源代码开放的,这是它与UNIX的不同之处。现在,Linux凭借优秀的设计,不凡的性能,加上IBM、Intel、CA、CORE、Oracle等国际知名企业的大力支持,市场份额逐步扩大,已成为与Windows和UNIX并存的三大主流操作系统之一。1.2 Linux的使用1.2.1 vi的使用1) vi的简单应用vi是linux环境下赫赫有名的文本编辑工具之一。进入vi编辑器的方法: vi filename.c 注:文件
6、名必须带有扩展名.c,如 filename.c否则无法通过编译;进入vi后要按:按“i”键从命令方式切换到输入方式;从输入方式切换到命令方式的方法:按“Esc”键保存文件 :w保存文件并退出 :wq不保存文件退出 :q!注:以上操作必须在命令方式下进行。2) 其他常用vi操作命令j,k,h,l:上下左右0:行首 $: 行尾 ctrl+f:后翻页 ctrl+b:前翻页 G:文件尾 数字G:数字所指定行 i,I: 插入命令,i在当前光标处插入,I行首插入 a,A: 追加命令,a在当前光标后追加,A在行末追加 o,O: 打开命令,o在当前行下打开一行,O在当前行上插入一行 x:删除光标处字符 dd:
7、删除当前行 d0:删除光标前半行 d$:删除光标后半行 r,R: 替换命令,r替换当前光标处字符,R从光标处开始替换/string:查找字符串 n : 继续查找 N : 反向继续查找 % :查找对应括号 u :取消上次操作 注:以上操作必须在命令方式下进行。1.2.2 gcc的使用gcc是linux下的一种c程序编译工具,使用方法如下(有提示符#的情况): 编译: gcc o filename1 filename.c其中: filename.c是源文件名,filename1 是目标文件名,o代表object 执行:./filenamel示例:键入一简单的程序:vi ab.c 按回车键输入以下代
8、码段,#include#includemain()printf(“aaaa”);按ESC键,再按“:WQ”(W是保存,Q是退出)出现提示符:root GGG-LINUX root#键入:gcc o ab ab.c进行编译。执行:./ab1.2.3主要系统调用函数1.2.1系统调用fork()功能:创建一个新的进程. 头文件:#include 说明:本系统调用产生一个新的进程, 叫子进程, 是调用进程的一个复制品. 调用进程叫父进程, 子进程继承了父进程的几乎所有的属性。 (1) 该子进程继承了父进程的程序空间,复制了父进程的数据段和栈段。也就是说不管是父进程还是子进程,在占有处理机后,都从fo
9、rk()调用的返回点开始运行;(2) 调用成功则对父进程返回子进程标识号pid;(3) 调用成功对子进程返回0, 这也是最方便的区分父子进程的方法。(4) 若调用失败则返回-1给父进程, 子进程不生成。 注意:如果fork()值0,0的数即是子进程号。但这时是父进程占有处理机。1.2.2系统调用wait(&status):功能: 等待子进程结束。(1)当有多个子进程时,任一个子进程结束即将控制返回调用者,并将子进程调用exit (status)时的status值送到&status指针所指单元中。(2)在控制返回调用者时,同时将所等到的子进程pid作为wait()系统调用函数的返回值。(3)wa
10、itpid(pid,):等待pid所指定的进程结束。(4)返回值:等待到一个子进程返回时,返回值为该子进程号;否则返回值为1。说明: 允许调用进程(即父进程)取得子进程的状态信息,调用进程将会挂起直到其一个子进程终止。1.2.3系统调用exit()功能: 终止进程. 语法: #include void exit(status) int status功能:调用进程被该系统调用终止。该系统调用发出后,操作系统将从系统中删除调用exit的进程,并将status值传给等待它结束的父进程。返回值: 无 1.2.4系统调用kill()功能: 向一个或一组进程发送一个信号。 语法:#include int
11、kill(pid, sig); pid_t pid; int sig;说明:向一个或一组进程发送一个信号,该信号由参数sig指定,为系统给出的信号表中的一个。Sig是signal的缩写。返回值: 调用成功则返回0,否则返回-1. kill -STOP pid: 发送SIGSTOP (17,19,23)停止一个进程,而并不消灭这个进程。kill -CONT pid: 发送SIGCONT (19,18,25)重新开始一个停止的进程。kill -KILL pid: 发送SIGKILL (9)强迫进程立即停止,并且不实施清理操作。kill -9 -1: 终止拥有的全部进程。SIGKILL和SIGSTO
12、P信号不能被捕捉、封锁或者忽略。1.2.5系统调用lockf()功能:应用、检测或删除打开文件的一个POSIX锁语法:#include int lockf(int fd, int cmd, off_t len);说明: 应用、检测或删除打开文件某部分的一个POSIX锁,文件通过fd指明,文件的描述符的请求操作通过cmd指明。#define F_ULOCK 0 解锁一个区域#define F_LOCK 1 上锁一个区域#define F_TLOCK 2 检测并上锁一个区域#define F_TEST 3 检测一个区域是否上锁文件上锁区域的请求起始于隐含的偏移并包好len字节,假如len为负,从p
13、ospos+len-1,这里pos为当前文件位置,假如len为零,则位置从当前文件位置延伸延伸到无限长,包括当前和以后的文件最后的位置。在所有情况下,位置可延伸到以前当前的文件的最后位置。在Linux中,这称为fcntl(2)的接口(一般会指明lockf 和fcntl的关系)。1.2.6 系统调用pipe()是用来建立管道的。语法: #include int pipe(int fd2); 这里fd1为写入端,fd0为读出端。功能:从管道里写或从管道里读。第二部分 实验内容实验项目一 熟悉LINUX基本命令及编程环境一、 实验类型本实验为验证性实验。二、 实验目的与任务1. 熟悉Linux操作系
14、统的安装和使用;熟悉使用Linux字符界面,窗口系统的常用命令。2. 掌握运用Linux常用的编程工具;掌握如何编辑、编译、运行程序。三、 实验准备1. 熟悉linux系统中常用命令及其功能2. 熟悉vi编辑器或Gedit编辑器的各项功能3. 复习C语言程序的编写。四、 实验内容1练习使用ls、cp、等命令。使用vi编辑器或Gedit编辑器用C语言编写一个HelloWorld程序,并保存。使用gcc对编写的程序进行编译,并生成相应的可执行程序。如果发生编译错误,仔细阅读错误提示,并回到编辑器中作出正确修改。运行生成的可执行程序,观察结果。熟悉怎么编辑一个程序(编辑,调试,运行见),输入一个简单
15、的C程序进行练习,参考练习程序如下:程序1#includemain()int p1;while(p1=fork()=-1);if(p1=0)putchar(B);else putchar(A);五、 注意事项gcc编译器不能编译不带扩展名的c语言程序。注意编译和运行程序的基本过程。注意熟练使用man命令来查看某条命令的含义及使用方式。实验项目二 进程管理一、 实验类型本实验为验证性实验。二、 实验目的1. 理解进程的概念,掌握父、子进程创建的方法。2. 认识和了解并发执行的实质,掌握进程的并发及同步操作。三、 实验预备知识1. fork()函数头文件:#include#include函数原型:
16、pid_t fork(void);(pid_t 是一个宏定义,其实质是int,被定义在#include中)返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1函数说明:一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。linux将复制父进程的地址空间内
17、容给子进程,因此,子进程有了独立的地址空间。为什么fork会返回两次?由于在复制时复制了父进程的堆栈段,所以两个进程都停留在fork函数中,等待返回。因为fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的,过程如图2.1。调用fork之后,数据、堆栈有两份,代码仍然为一份但是这个代码段成为两个进程的共享代码段都从fork函数中返回,箭头表示各自的执行处。当父子进程有一个想要修改代码段时,两个进程真正分裂。图2.1 fork()函数分裂示意图示例代码:#include /对于此程序而言此头文件用不到#include#includeintmain(int
18、argc,char* argv )intpid = fork();if(pid 0)printf(error!);elseif( pid = = 0 )printf(This is the child process!);else printf(This is the parent process! child process id = %d, pid);return0;fork函数的特点概括起来就是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。fork的另一个特性是所有由父进程打开的描述符都被复制到子进程中。父、子进程中相同编号的文件描述符在内核中指向同一个fil
19、e结构体,也就是说,file结构体的引用计数要增加。2. wait()函数头文件:#include#include函数原型:pid_t wait (int * status);返回值:如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。函数说明:wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束状态值请参考下面的waitpid()。
20、示例代码:#include#include#include#includeint main(intargc,char* argv)pid_t pid;int status,i;if(fork()= =0)printf(This is the child process .pid =%dn,getpid();exit(5);elsesleep(1);printf(This is the parent process ,wait for child.n);pid=wait(&status);i=WEXITSTATUS(status);printf(childs pid =%d .exit stat
21、us=%dn,pid , i);3. waitpid()函数头文件:#include#include函数原型:pid_t waitpid(pid_t pid,int * status,int options);返回值:如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。函数说明:waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。参数pid
22、 为欲等待的子进程识别码,其他数值意义如下:pid0 等待任何子进程识别码为pid 的子进程。参数option 可以为0 或下面的组合:WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。子进程的结束状态返回后存于status,底下有几个宏可判别结束情况:WIFEXITED(status)如果子进程正常结束则为非0 值。WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。WIFSIGNALED(status)如果子
23、进程是因为信号而结束则此宏值为真。WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。4. exit()函数头文件:#include函数原型:void exit(int status);返回值:无。函数说明:进程结束正常终止,返回结束状态。status为进程结束状态,是返回给父进程的一个整数,
24、以备查考。为了及时回收进程所占用的资源并减少父进程的干预,UNIX/LINUX利用exit( )来实现进程的自我终止,通常父进程在创建子进程时,应在进程的末尾安排一条exit( ),使子进程自我终止。exit(0)表示进程正常终止,exit(1)表示进程运行有错,异常终止。如果调用进程在执行exit( )时,其父进程正在等待它的终止,则父进程可立即得到其返回的整数。核心须为exit( )完成以下操作:(1)关闭软中断(2)回收资源(3)写记帐信息(4)置进程为“僵死状态”四、 实验内容1. 编写一C语言程序,实现在程序运行时通过系统调用fork( )创建两个子进程,使父、子三进程并发执行,父亲
25、进程执行时屏幕显示“I am father”,儿子进程执行时屏幕显示“I am son”,女儿进程执行时屏幕显示“I am daughter”。2. 多次连续反复运行这个程序,观察屏幕显示结果的顺序,直至出现不一样的情况为止。记下这种情况,试简单分析其原因。3. 修改程序,在父、子进程中分别使用wait()、exit()等系统调用“实现”其同步推进,并获取子进程的ID号及结束状态值。多次反复运行改进后的程序,观察并记录运行结果。五、 实验报告要求1. 列出实验内容1、3各程序清单,并以截图形式记录相应运行结果。2. 对实验运行结果进行分析:1)实验内容1运行结果为什么无固定顺序,fork()函
26、数创建进程是如何并发执行的。2)实验内容3是如何实现父子进程的同步执行的。实验项目三 进程调度一、 实验类型本实验为验证性实验。二、 实验目的1. 理解进程控制块和进程组织方式;2. 掌握时间片轮转调度算法实现处理机调度。三、 实验预备知识1. 实验基本原理进程控制块通过链表队列的方式组织起来,系统中存在运行队列和就绪队列(为简单起见,不设阻塞队列),进程的调度就是进程控制块在运行队列和就绪队列之间的切换。当需要调度时,从就绪队列中挑选一个进程占用处理机,即从就绪队列中删除一个进程,插入到运行队列中,当占用处理机的进程运行的时间片完成后,放弃处理机,即在运行队列中的进程控制块经过一段时间(时间
27、片)后,从该队列上删除,如果该进程运行完毕,则删除该进程(节点);否则,则插入到就绪队列中。2. 实验中使用的数据结构(1) PCB进程控制块内容包括参数进程名name;要求运行时间 runtime;已运行时间runedtime;本轮运行时间killtime。(2) 进程队列为简单起见,只设运行队列,就绪队列两种数据结构,进程的调度在这两个队列中切换,如图3.1所示。图3.1 PCB链表3. rand()函数和srand()函数库函数中系统提供了两个函数用于产生随机数:srand()和rand()。 函数一:int rand(void);从srand (seed)中指定的seed开始,返回一个
28、0,RAND_MAX(0x7fff)间的随机整数。函数二:void srand(unsigned seed);参数seed是rand()的种子,用来初始化rand()的起始值。函数rand()是真正的随机数生成器,而srand()会设置供rand()使用的随机数种子。如果你在第一次调用rand()之前没有调用srand(),那么系统会为你自动调用srand()。而使用同种子相同的数调用 srand()会导致相同的随机数序列被生成。srand(unsigned)time(NULL)则使用系统定时/计数器的值做为随机种子。每个种子对应一组根据算法预先生成的随机数,所以,在相同的平台环境下,不同时间
29、产生的随机数会是不同的,相应的,若将srand(unsigned)time(NULL)改为srand(TP)(TP为任一常量),则无论何时运行、运行多少次得到的“随机数”都会是一组固定的序列,因此srand生成的随机数是伪随机数。但是,要注意的是所谓的“伪随机数”指的并不是假的随机数。其实绝对的随机数只是一种理想状态的随机数,计算机只能生成相对的随机数即伪随机数。计算机生 成的伪随机数既是随机的又是有规律的一部份遵守一定的规律,一部份则不遵守任何规律。比如“世上没有两片形状完全相同的树叶”,这体现到了事物的特性差异性;但是每种树的叶子都有近似的形状,这正是事物的共性规律性。从这个角度讲,我们就
30、可以接受这样的事实了:计算机只能产生伪随机数而不是绝对的随机数。系统在调用rand()之前都会自动调用srand(),如果用户在rand()之前曾调用过srand()给参数seed指定了一个值,那么 rand()就会将seed的值作为产生伪随机数的初始值;而如果用户在rand()前没有调用过srand(),那么系统默认将1作为伪随机数的初始值。如果给了一个定值,那么每次rand()产生的随机数序列都是一样的。所以为了避免上述情况的发生我们通常用srand( (unsigned) time(0) )或者srand(unsigned)time(NULL)来 产生种子。如果仍然觉得时间间隔太小,可以
31、在(unsigned)time(0)或者(unsigned)time(NULL)后面乘上某个合适的整数。 例如,srand(unsigned)time(NULL)*10)。另外,关于time_t time(0):time_t被定义为长整型,它返回从1970年1月1日零时零分零秒到目前为止所经过的时间,单位为秒。srand()、rand()用法举例:#include#includevoid main() int i,j; srand(10); /srand(int)time(0); for (i=0; i10; i+) j = (int) (rand()%20; printf( %dn , j)
32、; 4. malloc()函数头文件:#include函数原型:void * malloc(unsigned int size);函数说明:其作用是在内存的动态存储区中分配一个长度为size的连续空间,此函数的值(即“返回值”)是一个指向分配域其实地址的指针(类型为void)。若此函数未能成功执行则返回空指针。5. 程序流程图图3.2模拟进程调度的流程图6. 部分参考程序(1) PCB数据结构struct PCB int name; int runtime;int runedtime; int killtime;struct PCB *next;typedef struct PCB PCB;(
33、2) 创建就绪列表#define LEN sizeof(PCB)PCB *runqueue;/运行队列指针PCB *top,*tail,*temp;/就绪队列指针int i;srand(int)time(0);for(i=0;iname=i; temp-runtime=rand()%15; temp-runedtime=0; temp-next=NULL; temp-killtime=0; if(i=0) top=temp; tail=temp; else tail-next=temp; tail=temp; printf(process name %d, runtime=%d, runedt
34、ime=%d,killtime=%dn, tail-name,tail-runtime,tail-runedtime,tail-killtime); 7. 按时间片轮转算法进行进程调度的过程描述。第1步:取就绪队列的队首结点为运行队列的结点,修改就绪队列队首指针后移;第2步:调度运行队列结点,即运行队列结点的要求运行时间减去时间片时间;第3步:a若修改后要求运行时间=0,则表示该进程结点运行完毕,修改进程结点的PCB信息,记录runtime,runedtime,killtime等信息。并将结点信息输出。b否则,表示该进程结点未完成,记录runtime,runedtime,killtime等信息
35、,将结点信息输出。并将该结点置于就绪队列的队尾,等待下次调度,同时修改队尾指针。第4步:若就绪队列非空,则继续执行第1步,直至就绪队列为空。四、 实验内容1. 建立合理的PCB数据结构,建立含有8个进程结点的就绪队列,每个进程的要求运行时间随机产生,要求每个进程的要求运行时间不大于15。2. 设置时间片大小(36),使用时间片轮转调度算法实现处理机调度。五、 实验报告要求1. 列出实验内容所要求的程序清单,并以截图形式记录相应运行结果;2. 对实验运行结果进行分析:如果时间片设置值过大或过小,会对进程的调度产生何种影响。实验项目四 进程通信一、 实验类型本实验为综合性实验。二、 实验目的1.
36、了解什么是消息,熟悉消息传送原理。2. 了解和熟悉共享存储机制。3. 掌握消息的发送与接收的实现方法。三、 实验预备知识任务一 消息的发送和接收1. 实验基本原理消息(message)是一个格式化的可变长的信息单元。消息机制允许由一个进程给其它任意的进程发送一个消息。当一个进程收到多个消息时,可将它们排成一个消息队列。消息使用两种重要的数据结构:一是消息首部,其中记录了一些与消息有关的信息,如消息数据的字节数;二是消息队列头表,其每一表项是作为一个消息队列的消息头,记录了消息队列的有关信息。消息机制的数据结构:struct msgform long mtype; char mtext1024;
37、(1)消息首部记录一些与消息有关的信息,如消息的类型、大小、指向消息数据区的指针、消息队列的链接指针等。(2)消息队列头表其每一项作为一个消息队列的消息头,记录了消息队列的有关信息如指向消息队列中第一个消息和指向最后一个消息的指针、队列中消息的数目、队列中消息数据的总字节数、队列所允许消息数据的最大字节总数,还有最近一次执行发送操作的进程标识符和时间、最近一次执行接收操作的进程标识符和时间等。(3)消息队列的描述符UNIX中,每一个消息队列都有一个称为关键字(key)的名字,是由用户指定的;消息队列有一消息队列描述符,其作用与用户文件描述符一样,也是为了方便用户和系统对消息队列的访问。2. m
38、sgget( )函数头文件:#include#include#include函数原型:int msgget(key_t key, int msgflag);函数说明:创建一个消息,获得一个消息的描述符。系统内核将搜索消息队列头表,确定是否有指定名字的消息队列。若无,系统内核将分配一新的消息队列头,并对它进行初始化,然后给用户返回一个消息队列描述符,否则它只是检查消息队列的许可权便返回。系统调用格式:msgqid=msgget(key,flag)。其中:msgqid 是该系统调用返回的描述符,失败则返回-1。msgget()函数的第一个参数是消息队列对象的关键字(key),函数将它与已有的消息队
39、列对象的关键字进行比较来判断消息队列对象是否已经创建。而函数进行的具体操作是由第二个参数msgflg 控制的。它可以取下面的几个值:IPC_CREAT : 如果消息队列对象不存在,则创建之,否则则进行打开操作;IPC_EXCL: 和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建之,否则产生一个错误并返回。 如果单独使用IPC_CREAT 标志,msgget()函数要么返回一个已经存在的消息队列对象的标识符,要么返回一个新建立的消息队列对象的标识符。如果将IPC_CREAT 和IPC_EXCL标志一起使用,msgget()将返回一个新建的消息对象的标识符,或者返回-1。如
40、果消息队列对象已存在,IPC_EXCL 标志本身并没有太大的意义,但和IPC_CREAT 标志一起使用可以用来保证所得的消息队列对象是新创建的而不是打开的已有的对象。除了以上的两个标志以外,在msgflg 标志中还可以有存取权限控制符。这种控制符的意义和文件系统中的权限控制符是类似的。3. msgsnd( )函数头文件:#include#include#include函数原型:int msgsnd(int msqid, const void *msgp, intt msgsz, int msgflg);函数说明:在消息队列上进行收发消息,为了发送消息,调用进程对消息队列进行写入时必须有写权能。
41、成功执行时返回0,失败时返回-1。其中msgqid是返回消息队列的描述符;msgp是指向用户消息缓冲区的一个结构体指针。缓冲区中包括消息类型和消息正文,即 long mtype; /*消息类型*/ char mtext ; /*消息的文本*/ msgsz指示由msgp指向的数据结构中字符数组的长度;即消息的长度。这个数组的最大值由MSG-MAX( )系统可调用参数来确定。msgflag参数是控制函数行为的标志,取值可以是:0,表示忽略。若在标志msgflag中未设置IPC_NOWAIT位,则当该消息队列中的字节数超过最大值时,或系统范围的消息数超过某一最大值时,调用msgsnd进程睡眠。若是设
42、置IPC_NOWAIT,则在此情况下,msgsnd立即返回。对于msgsnd( ),系统内核须完成以下工作:(1)对消息队列的描述符和许可权及消息长度等进行检查。若合法才继续执行,否则返回;(2)系统内核为消息分配消息数据区。将用户消息缓冲区中的消息正文,拷贝到消息数据区;(3)分配消息首部,并将它链入消息队列的末尾。在消息首部中须填写消息类型、消息大小和指向消息数据区的指针等数据;(4)修改消息队列头中的数据,如队列中的消息数、字节总数等。最后,唤醒等待消息的进程。4. msgrcv ( )函数头文件:#include#include#include函数原型:int msgrcv(int m
43、sqid, void *msgp, int msgsz, long msgtyp, int msgflg);函数说明:msgrcv ( )函数用来接收一消息。从指定的消息队列中接收指定类型的消息。其中,msgqid,msgp,msgsz,msgflg与msgsnd中的对应参数相似,msgtyp是规定要读的消息类型,msgflg规定倘若该队列无消息,系统内核应做的操作,是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如此时设
44、置了IPC_NOWAIT标志,则立即返回,若在flag中设置了MS_NOERROR,且所接收的消息大于size,则系统内核截断所接收的消息。对于msgrcv系统调用,系统内核须完成下述工作:(1)对消息队列的描述符和许可权等进行检查。若合法,就往下执行;否则返回;(2)根据msgtyp的不同分成三种情况处理:msgtyp=0,接收该队列的第一个消息,并将它返回给调用者;msgtyp为正整数,接收类型type的第一个消息;msgtyp为负整数,接收小于等于type绝对值的最低类型的第一个消息。(3)当所返回消息大小等于或小于用户的请求时,系统内核便将消息正文拷贝到用户区,并从消息队列中删除此消息
45、,然后唤醒睡眠的发送进程。但如果消息长度比用户要求的大时,则做出错返回。5. msgctl ( )函数头文件:#include#include#include函数原型:int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );函数说明:系统调用msgctl ( )用来控制对消息队列的操作。其中,函数调用成功时返回0,不成功则返回-1。buf是用户缓冲区地址,供用户存放控制参数和查询结果;cmd是规定的命令。命令可分三类:(1)IPC_STAT。查询有关消息队列情况的命令。如查询队列中的消息数目、队列中的最大字节数、最后一个发送消息的进程标
46、识符、发送时间等;(2)IPC_SET。按buf指向的结构中的值,设置和改变有关消息队列属性的命令。如改变消息队列的用户标识符、消息队列的许可权等;(3)IPC_RMID。消除消息队列的标识符。msgqid_ds 结构定义如下:struct msgqid_ds struct ipc_perm msg_perm; /*许可权结构*/ short pad17; /*由系统使用*/ ushort msg_qnum; /*队列上消息数*/ ushort msg_qbytes; /*队列上最大字节数*/ ushort msg_lspid; /*最后发送消息的PID*/ ushort msg_lrpid;
47、 /*最后接收消息的PID*/ time_t msg_stime; /*最后发送消息的时间*/ time_t msg_rtime; /*最后接收消息的时间*/ time_t msg_ctime; /*最后更改时间*/ ;struct ipc_perm ushort uid; /*当前用户*/ ushort gid; /*当前进程组*/ ushort cuid; /*创建用户*/ ushort cgid; /*创建进程组*/ ushort mode; /*存取许可权*/ short pid1; long pad2; /*由系统使用*/ 6. 样例程序 /client_ex.c 发送端#inclu
48、de#include#include #include #include #define MSGKEY 75struct msgform long mtype; char mtext1024;msg;int msgqid;void client() msgqid=msgget(MSGKEY,0777); /*打开75#消息队列*/ msg.mtype=1; msg.mtext1=a; printf(client)sentn); msgsnd(msgqid,&msg,1024,0); /*发送消息*/ exit(0);int main( ) client( ); /server_ex.c 接收端
49、#include#include#include #include #include #define MSGKEY 75struct msgform long mtype; char mtext1024;msg;int msgqid;void server( ) msgqid=msgget(MSGKEY,0777|IPC_CREAT); /*创建75#消息队列*/ msgrcv(msgqid,&msg,1024,0,0); /*接收消息*/ printf(%c ,msg.mtextmsg.mtype); printf(server)receivedn); msgctl(msgqid,IPC_R
50、MID,0); /*删除消息队列,归还资源*/ exit(0);int main( ) server( );任务二 使用共享存储区通信1. 实验基本原理共享存储区(Share Memory)是UNIX系统中通信速度最高的一种通信机制。该机制可使若干进程共享主存中的某一个区域,且使该区域出现(映射)在多个进程的虚地址空间中。另一方面,一个进程的虚地址空间中又可连接多个共享存储区,每个共享存储区都有自己的名字。当进程间欲利用共享存储区进行通信时,必须先在主存中建立一共享存储区,然后将它附接到自己的虚地址空间上。此后,进程对该区的访问操作,与对其虚地址空间的其它部分的操作完全相同。进程之间便可通过对共享存储区中数据的读、写来进行直接通信。图4.1列出二个进程通过共享一个共享存储区来进行通信的例子。其中,进程A将建立的共享存储区附接到自己的AA区域,进程B将它附接到自己的BB区域。图4.1 共享存储区应当指出,共享存储区机制只为进程提供了用于实现通信的共享存储区和对共享存储区进行操作的手段,然而并未提供对该区进行互斥访问及进程同步的措施。因而当用户需要使用该机制时,必须自己设置同步和互斥措施才能保证实现正确的通信。2. shmget ( )函数头文件:#include#include#include函数原型:int shmget(key_
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 娄彻链霉菌YC117防控烟草黑胫病及其作用机理研究
- 基于深度学习的铁路机车乘务员违规行为检测研究
- 2025至2030年紫木纹砂岩板材项目投资价值分析报告
- 原子Co负载(001)TiO2纳米材料合成及其光助活化过硫酸盐降解有机污染物
- 过渡金属氧化物改性棉织物的制备及其催化氧化壬烯醛的研究
- 2025至2030年活体指纹采集仪项目投资价值分析报告
- 2025至2030年桔瓤生产线项目投资价值分析报告
- 坪坦河流域侗族风雨桥营造技艺研究
- 2025至2030年工业酒精项目投资价值分析报告
- 太极拳运动对青少年平衡能力和抑制控制能力影响的实验研究
- 微量注射泵安全使用和维护保养
- 高二物理人教版(2019)选择性必修第一册教学设计
- 《短视频拍摄与制作》课件-2短视频前期创意
- 污水处理厂运营维护移交 投标方案(技术方案)
- 部编版历史八年级上册 第八单元 教学设计
- 高中英语元宵节猜灯谜活动英文课件
- 家校合作共育课件
- 2023年全国报关员考试真题试卷及答案
- 春节后复产复工培训
- 新生儿气胸穿刺
- 《红楼梦》重点情节梳理
评论
0/150
提交评论