《2011操作系统实验指导书.docx》由会员分享,可在线阅读,更多相关《2011操作系统实验指导书.docx(28页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、进入学校的linlux 系统:Telnet 202.116.57.246操作系统试验指导书高文宇gwy广东商学院信息学院2023 年 9 月10名目操作系统试验指导书1试验一 Linux 命令及编辑器Vi 的使用4试验二 Linux 系统治理实践10试验三 进程掌握16试验四 进程通信20试验五 进程同步124试验六 进程同步226试验一 Linux 命令及编辑器 Vi 的使用一、试验目的与要求(1) 体会多用户、多任务网络操作系统Linux 的工作特点;(2) 理解操作系统的分类、相关概念和资源治理功能。二、预备学问(1) Linux 命令的格式bash 命令的一般格式是:命令名 选项 参数
2、 1 参数 2 例如:cp f file1.c myfile.c需要留意的是:命令名必需是小写的英文字母一般格式中由方括号括起来的局部是可选的 选项以“-”开头,多个选项可用“-”连起来命令行的参数供给命令运行的信息或者命令执行过程中所使用的文件名假设命令行中没有供给参数,则命令使用标准文件进展输入/输出命令在正常执行后返回一个 0 值,表示执行成功Linux 操作系统的联机帮助对每个命令的准确语法都做了说明(2) Linux 的联机帮助命令man三、试验内容(1) 登录、退出和关机1、 超级用户与一般用户超级用户是对系统的一切资源均具有访问权限的用户,即系统治理员,用户名为:root, 命令
3、提示符为:#;一般用户由超级用户创立和删除,仅具有超级用户指定的访问权限,命令提示符为:$。超级用户和一般用户可以相互切换;要养成用一般用户登录、使用系统的习惯。2、 登录开机启动后,系统提示: Login:用户名Password:口令输入超级用户名 root,消灭提示符:#;输入一般用户名,消灭提示符:$。在提示符后就可以输入各种Linux 命令了。3、 创立和删除用户必需在超级用户下完成。创立用户:# useradd 用户名创立/修改口令: # passwd 口令删除用户:# userdel r 用户名4、 用户切换一般用户切换到超级用户:$ su password:口令超级用户切换到一般
4、用户:# su 一般用户名5、 退出为避开其他用户非法盗用自己的用户名,停顿使用系统时要退出。退出系统有很多方法: 可以在命令提示符下键入exit 或 logout 命令,也可以使用组合键Ctrl+d。6、 关机一般用户没有关机权限,只有超级用户才能关闭系统。关机方式有命令方式和组合键Ctrl+Alt+Del 两种方式,可以使用halt 或 shutdown 命令: # halt显示System halted 时才可以关闭电源 # shutdown 系统默认 2 分钟后关机shutdown h now系统马上关机 shutdown r now系统马上重开机shutdown h 20:25系统将
5、在 20:25 分关机 shutdown h +10系统在 10 分钟后关机(2) 常用命令的使用1、 ls 命令功能:查看指定名目下的文件和名目。格式:ls options filename/dirname常用选项说明:-a 显示全部文件和名目,包括隐含文件-l 显示文件的完整信息-f 对文件添加一特定后缀字符指出其类型/ 子名目* 可执行文件无 一般文件.开头 隐含文件-r 将文件以相反次序显示-t 将文件以建立时间先后列出-R 假设名目下有文件,则文件也依序列出例如:ls ltr s*将当前名目下全部以s 开头的文件按建立时间的逆序列出完整信息ls lR bin将bin 名目下所知名目及
6、文件的具体信息列出ls alf将当前名目下包括隐含文件在内的全部文件信息完整列出,并在文件名后添加特别后缀以表示文件类型2、 man 命令功能:查看某个命令的使用方法。格式: man 命令名3、 clear 命令功能:清屏。格式: clear 4、 cat 命令功能:显示或链接ASCALL 文件。格式:cat 文件名例如:cat text显示text 的文件内容cat file1 file2依次显示file1 和 file2 的内容cat file1file2将 file1 的内容附加到file2 后面,但file1 仍存在cat file1将键盘输入以Ctrl+c 完毕的内容输出到file1
7、 5、 pwd 命令功能:显示当前名目。格式:pwd6、 cd 命令功能:进入或修改指定的名目。格式:cd 名目名7、 mkdir 命令功能:建立的名目。 格式:mkdir 的名目名8、 rmdir 命令功能:删除空名目。 格式:rmdir 空名目名9、 rm 命令功能:删除指定的文件或名目。格式:rm options filename/dirname常用选项说明:-i 删除前逐一询问确认-f 即使文件属性为只读,也直接删除无需确认-r 将指定名目下的全部文件及子名目一并删除-v 显示指令执行过程例如:rm i *.c删除 C 语言程序文件,删除前逐一询问确认rm r finished删除fi
8、nished 子名目及子名目中的全部文件10、du 命令功能:显示当前名目所占用的硬盘空间。格式:du abC 名目/文件名称选项说明:-a 表示要显示所知名目及每个名目所占用的空间,单位是Kb-b 表示显示空间大小的单位是byte-C 表示显示一个名目的总空间的大小不加任何参数,则显示当前名目下各名目占用的空间及全部文件所占总空间11、df 命令功能:查看硬盘目前所剩的空间。格式:df12、cp 命令功能:复制文件或名目。格式:cp r 源文件/名目名 目标文件/名目名例如:cp file1.c file2.doc将 file1.c 复制为file2.doc cp r /tmp/ /abc/
9、将 tmp 子名目中的文件及下属子名目一同复制到abc 子名目13、mv 命令功能:移动文件或名目。格式:mv 源文件/名目名 目标文件/名目名14、more 命令功能:按页查看指定的文件。格式:more options filename常用选项说明:-num 一次显示的行数+num 从第num 行开头显示-d 在屏幕下方显示提示信息Press space to continue,q to quit.-l 取消遇见特别字符L 时会暂停的功能-f 计算行数时按实际的行数,而非自动换行的行数记数-p 不以卷动的方式显示每一页,而是先清屏后显示-c 先显示内容再去除旧资料-s 将连续两行以上的空白行
10、代换为一行空白行filenames 欲显示内容的文件,可为复数个数例如:more s testfile逐页显示文件testfile 的内容,如有连续两行以上空白行则以一行空白行显示more +20 testfile从第 20 行开头显示文件testfile 的内容15、find 命令功能:将符合组合条件expression 的文件列出来。格式:find path expression常用参数说明:命令中第一个“-”之前的局部为path,之后的局部为expression。假设path 是空字符串则使用目前路径,假设expression 是空字符串则使用-print 为默认expression。常
11、用 expression:-group 查找符合指定之群组名称的文件或名目-help 在线帮助-print 假设find 命令的返回值为true,就将文件或名目名称在标准输出设备输出。格式为每列一个名称,每个名称前皆有“./”字符串-user 查找符合指定的拥有者名称的文件或名目例如:find . name “*.c”将当前名目及其子名目下全部后缀名为c 的文件列出find . ftype f将当前名目及其子名目下全部一般文件列出find . ctime -20将当前名目及其子名目下全部最近20 分钟内更过的文件列出(3) 在Linux 中编辑文档vi 编辑器vi 编辑器的三种工作模式: 命令
12、模式Command mode:掌握屏幕光标的移动、字符的插入或删除、字符的移动或复制、进入插入模式或底线命令模式; 插入模式Insert mode:完成字符的输入; 底线命令模式Last line mode:存储文件或退出编辑器,也可设置编辑环境。 vi 工作模式的切换: 进入命令模式:在命令提示符后输入:vi ; 切换到插入模式:在命令模式下按键i、a、o 进入插入模式i插入:在当前光标位置输入字符; a增加:从当前光标的前一个位置开头输入字符; o插入行:从行行首开头输入字符。 切换到命令模式:在插入模式下按Esc 键; 切换到底线命令模式:在命令模式下按“:”进入底线命令模式。四、试验软
13、硬件环境硬件要求:P4 2.0G 1G 内存 60G 硬盘以上电脑软件要求:C、C+编程环境,Java 编程环境五、试验步骤试验每人单独完成,独立练习上述各种命令的使用。六、试验考核方法提交试验报告,具体介绍试验中所做的工作,遇到的问题,解决方法,试验后的体会和设想。在 man 的命令中遇到了跳不出该命令的状况,从网上搜寻找到了安“Q”解决了,另外在查找文件的时候遇到了中文的输入不会,用CTRL+SPACE 键进展输入七、附:思考题(1) 如何查看文件名目?如何查看文件内容?Find 加文件名CAT 加文件名(2) 如何创立子名目?进入指定的子名目?以及删除子名目及其下的文件?(3) 如何查看
14、硬盘空间?(4) 如何复制或移动文件?(5) 如何使用vi 编辑器进展源程序的编辑?如何编译和运行程序?试验二 Linux 系统治理实践一、试验目的与要求二、预备学问三、试验内容(1) Linux 的进程治理命令Linux 是一个多用户多任务的操作系统。多用户是指多个用户可以在同一时间使用计算机系统;多任务是指 Linux 可以同时执行几个任务,它可以在还未执行完一个任务时又执行另一项任务。在 Linux 系统上全部运行的东西都可以称之为一个进程。每个用户任务、每个系统治理守护进程,都可以称之为进程。Linux 用分时治理方法让全部的任务共同共享系统资源。下面就来看一看如何掌握这些进程。1、启
15、动进程在 Linux 系统中有两种启动进程的方法:l 直接输入命令,就将直接启动一个进程? 在一般状况下,进程将在前台执行,这时我们无法再执行的命令? 假设我们在命令之后加上一个“&”,那行进程将会放在后台执行,我们仍旧可以执行的命令l 通过 at、cron、crontab 命令可以像Windows 中的打算任务一样定时启动某个进程,具体的使用方法大家可以使用man 命令名来查询。2、查看进程在 Linux 系统中,可以使用ps 命令来查看正在运行的进程。例如: 列出属于当前用户的进程:# psPID TTY TIME CMD16767 pts/1 0:00 ps18029 pts/1 0:0
16、0 bash其中PID 代表进程ID,TTY 是该进程是由哪个掌握台启动的,CMD 则是命令。假设想列出更具体的信息,则可使用命令:“ps -auxw”。3、终止进程一个进程在任务完成之后,将会自动完成。假设要中途中止该进程的话,有两种方法:l 对于在前台运行的程序,直接通过组合键CTRL+C 就可以中止进程;l 而对于在后台运行的程序,则需要通过前面介绍的ps 命令找到它的进程号,然后使用“kill 进程号”来终止该进程。(2) Linux 的输入输出和重定向1、标准输入与输出在 Linux 中执行一个程序或命令时通常会自动翻开三个标准文件,即标准输入文件stdin,通常对应终端的键盘,标准
17、输出文件stdout和标准错误输出文件stderr,这两个文件都对应终端的屏幕。进程从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。以 cat 命令为例,cat 命令的功能是从命令行给出的文件中读取数据,并将这些数据直接送到标准输出。假设使用如下命令:$ cat config将会把文件config 的内容依次显示到屏幕上。但是,假设cat 的命令行中没有参数,它就会从标准输入中读取数据,并将其送到标准输出。例如:$ catHello world这一行是输入的Hello world这一行是cat 命令输出的 yeBye$用户输入的每一行都马上被ca
18、t 命令输出到屏幕上。输出到终端屏幕上的信息只能看不能修改,也无法保存。为了解决上述问题,Linux 系统为输入、输出的传送引入了另外两种机制,即输入/输出重定向和管道。2、输入重定向输入重定向是指把命令或可执行程序的标准输入重定向到指定的文件中。也就是说, 输入可以不来自键盘,而来自一个指定的文件。输入重定向主要用于转变一个命令的输入源, 特别是转变那些需要大量输入的输入源。例如,命令wc 统计指定文件包含的行数、单词数和字符数。假设仅在命令行上键入:$ wcwc 将等待用户告知它统计什么,这时 shell 就好象死了一样,从键盘键入的全部文本都消灭在屏幕上,但并没有什么结果,直至按下ctr
19、l+d,wc 才将命令结果写在屏幕上。假设给出一个文件名作为 wc 命令的参数,如下例所示,wc 将返回该文件所包含的行数、单词数和字符数。$ wc /etc/passwd20 23 726 /etc/passwd$另一种把/etc/passwd 文件内容传给 wc 命令的方法是重定向 wc 的输入。输入重定向的一般形式为:命令文件名。可以用下面的命令把 wc 命令的输入重定向为/etc/passwd 文件:$ wc 文件名。例如:$ ls test1上述命令将 ls 命令的输出保存到一个名为 test1 的文件中,假设 符号后边的文件已存在,那么这个文件将被掩盖。为避开输出重定向中指定文件只
20、能存放当前命令的输出重定向的内容,Linux 中还供给了输出重定向的追加机制。输出追加重定向与输出重定向的功能格外相像,区分仅在于输出追加重定向的功能是把命令或可执行程序的输出结果追加到指定文件的最终,而不是掩盖原有文件。假设要将一条命令的输出结果追加到指定文件的后面,可以使用追加重定向操作符。形式为:命令文件名。例如:$ ls *.txt test1上述命令将ls 命令的输出保存到一个名为test1 的文件中,test1 已存在,那么 ls 输出将被追加到test1 的末尾。和程序的标准输出重定向一样,程序的错误输出也可以重定向。使用符号 2或追加符号 2表示对错误输出设备重定向。例如下面的
21、命令:$ ls /home/student 2 err上述命令执行时,可在屏幕上看到程序的正常输出结果,但同时又将命令运行的任何错误信息送到文件err 中,以备将来检查用。此外,还可以使用另一个输出重定向操作符&将标准输出和错误输出同时送到同一文件中。例如:$ ls /home/student & output使用“&”重定向操作符可以使得一个程序或命令的运行不会在屏幕上显示任何信息, 而是将输出保存到一个文件中,这种方式便利了程序的后台运行。(3) Linux 的管道通信将一个程序或命令的输出作为另一个程序或命令的输入,有两种方法,一种是通过一个临时文件将两个命令或程序结合在一起;另一种是
22、Linux 所供给的管道功能。这种方法比前一种方法更好。管道可以把一系列命令连接起来,这意味着第一个命令的输出会作为其次个命令的输入通过管道传给其次个命令,其次个命令的输出又会作为第三个命令的输入,以此类推。显示在屏幕上的是管道行中最终一个命令的输出假设命令行中未使用输出重定向。通过使用管道符“|”来建立一个管道行。例如有如下命令:$ ls /home/student | wc -w上述命令的执行结果是将ls /home/student 的输出作为wc w 的输入。(4) Linux 的C 编译器1、GCC为 Linux 开发应用程序时,绝大多数状况下使用的都是C 语言,因此几乎每一位Linu
23、x 程序员面临的首要问题都是如何敏捷运用C 编译器。目前 Linux 下最常用的C 语言编译器是 GCCGNU Compiler Collection,它是GNU 工程中符合ANSI C 标准的编译系统,能够编译用C、C+和 Object C 等语言编写的程序。GCC 不仅功能格外强大,构造也特别敏捷。最值得称道的一点就是它可以通过不同的 前端模块来支持各种语言,如 Java、 Fortran、Pascal、Modula-3 和 Ada 等。开放、自由和敏捷是Linux 的魅力所在,而这一点在GCC 上的表达就是程序员通过它能够更好地掌握整个编译过程。在使用 GCC 编译程序时,编译过程可以被
24、细分为四个阶段: 预处理Pre-Processing 编译Compiling 汇编Assembling 链接LinkingLinux 程序员可以依据自己的需要让GCC 在编译的任何阶段完毕,以便检查或使用编译器在该阶段的输出信息,或者对最终生成的二进制文件进展掌握,以便通过参加不同数量和种类的调试代码来为今后的调试做好预备。和其它常用的编译器一样,GCC 也供给了敏捷而强大的代码优化功能,利用它可以生成执行效率更高的代码。GCC 供给了 30 多条警告信息和三个警告级别,使用它们有助于增加程序的稳定性和可移植性。此外,GCC 还对标准的C 和 C+语言进展了大量的扩展,提高程序的执行效率, 有
25、助于编译器进展代码优化,能够减轻编程的工作量。2、GCC 的使用在学习使用 GCC 之前,下面的这个例子能够帮助用户快速理解 GCC 的工作原理,并将其马上运用到实际的工程开发中去。首先用生疏的编辑器输入清单1 所示的代码:清单 1:hello.c#include int main(void)printf (“Hello world, Linux programming!n“); return 0;然后执行下面的命令编译和运行这段程序:# gcc hello.c -o hello # ./helloHello world, Linux programming!从程序员的角度看,只需简洁地执行一
26、条 GCC 命令就可以了,但从编译器的角度来看, 却需要完成一系列格外繁杂的工作。首先,GCC 需要调用预处理程序 cpp,由它负责开放在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;接着,GCC 会调用ccl 和 as 将处理后的源代码编译成目标代码;最终,GCC 会调用链接程序ld,把生成的目标代码链接成一个可执行程序。为了更好地理解GCC 的工作过程,可以把上述编译过程分成几个步骤单独进展,并观看每步的运行结果。第一步是进展预编译,使用-E 参数可以让GCC 在预处理完毕后停顿编译过程:#gcc -E hello.c -o hello.i此时假设查看 hello.c
27、pp 文件中的内容,会觉察 stdio.h 的内容确实都插到文件里去了,而其它应当被预处理的宏定义也都做了相应的处理。下一步是将 hello.i 编译为目标代码,这可以通过使用-c 参数来完成:#gcc -c hello.i -o hello.oGCC 默认将.i 文件看成是预处理后的 C 语言源代码,因此上述命令将自动跳过预处理步骤而开头执行编译过程,也可以使用-x 参数让GCC 从指定的步骤开头编译。最终一步是将生成的目标文件链接成可执行文件:#gcc hello.o -o hello在承受模块化的设计思想进展软件开发时,通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用
28、 GCC 能够很好地治理这些编译单元。假设有一个由 foo1.c 和 foo2.c 两个源文件组成的程序,为了对它们进展编译,并最终生成可执行程序foo,可以使用下面这条命令:#gcc foo1.c foo2.c -o foo假设同时处理的文件不止一个,GCC 仍旧会依据预处理、编译和链接的过程依次进展。假设深究起来,上面这条命令大致相当于依次执行如下三条命令:# gcc -c foo1.c -o foo1.o # gcc -c foo2.c -o foo2.o # gcc foo1.o foo2.o -o foo在编译一个包含很多源文件的工程时,假设只用一条GCC 命令来完成编译是格外铺张时
29、间的。假设工程中有 100 个源文件需要编译,并且每个源文件中都包含 10000 行代码,假设像上面那样仅用一条 GCC 命令来完成编译工作,那么 GCC 需要将每个源文件都重编译一遍,然后再全部连接起来。很明显,这样铺张的时间相当多,尤其是当用户只是修改了其中某一个文件的时候,完全没有必要将每个文件都重编译一遍,由于很多已经生成的目标文件是不会转变的。要解决这个问题,关键是要敏捷运用 GCC,同时还要借助像 Make 这样的工具。四、试验软硬件环境硬件要求:P4 2.0G 1G 内存 60G 硬盘以上电脑软件要求:C、C+编程环境,Java 编程环境五、试验步骤试验每人单独完成,独立设计算法
30、,用C、C+或Java 实现。六、试验考核方法提交程序包含说明和注释,程序产生的数据文件 Inputdata,程序处理后的数据文件 OutputData,以上都是电子文档;另外每个同学分别提交纸质的试验报告,具体介绍试验中的工作,遇到的问题,解决方法,试验后的体会和设想。七、附:思考题试验三 进程掌握一、试验目的与要求(1) 加深对进程概念的理解,明确进程与程序的区分;(2) 进一步生疏并发进程的实质;(3) 分析进程竞争资源的现象,学习解决进程互斥的方法;(4) 了解Linux 系统中进程通信的根本原理。二、预备学问(1) 阅读Linux 的sched.c 源码文件,加深对进程治理概念的理解
31、;(2) 阅读Linux 的fork.c 源码文件,分析进程的创立过程。三、试验内容(1) 进程的创立任务:编写一段程序,利用 fork创立两个子进程,其中父进程显示字符“a”,两个子进程分别显示字符“b”和“c”。观看和记录屏幕上的显示结果,并分析缘由。程序: #include mainint p1,p2;while (p1=fork)= =-1);/*创立子进程 p1*/ if (p1= =0)/*子进程 1 创立成功*/putchar(b);elsewhile (p2=fork)= =-1);/*创立子进程 p2*/ if (p2= =0)/*子进程 2 创立成功*/putchar(c)
32、;elseputchar(a);/*父进程执行*/结果:bca有时会消灭bac分析:理论分析看,输出 bac,acb 等状况都有可能。由于 fork( )创立进程所需的时间多于输出一个字符需要的时间,故在父进程创立子进程2 的同时,子进程 1 输出了字符“b“; 而子进程 2 和父进程的输出次序是随机的,所以消灭上述可能的输出挨次。(2) 进程的掌握任务:将以上程序的输出由一个字符分别改为一句话,观看和分析结果;假设利用系统调用lockf给每个进程加锁实现进程间的互斥,再观看和分析结果。程序 1:#include mainint p1,p2;while (p1=fork)= =-1);/*创立
33、子进程 p1*/ if (p1= =0)/*子进程 1 创立成功*/for (i=0;i500;i+)printf(“son%dn”,i);/*输出 500 个字符串“son“*/ elsewhile (p2=fork)= =-1);/*创立子进程 p2*/ if (p2= =0)/*子进程 2 创立成功*/for (i=0;i500;i+)printf(“daughter%dn”,i);/*输出 500 个字符串“daughter“*/ elsefor (i=0;i500;i+)/*父进程执行*/ printf(“father%dn”,i);/*输出 500 个字符串“children“*/
34、结果: son daughter children 或son daughter.son children 等等分析:由于函数printf( )输出的字符串之间不会被中断,故字符串内部的挨次不变;但由于进程并发执行时的调度挨次和处理机安排的问题,输出字符串的先后挨次随执行的不同而不同。程序 2:#include mainint p1,p2,i;while (p1=fork)= =-1);/*创立子进程 p1*/ if (p1= =0)/*子进程 1 创立成功*/lockf(1,1,0);for (i=0;i500;i+) printf(“son%dn”,i);lockf(1,0,0);elsew
35、hile (p2=fork)= =-1);/*创立子进程 p2*/ if (p2= =0)/*子进程 2 创立成功*/lockf(1,1,0);for (i=0;i500;i+) printf(“daughter%dn”,i);lockf(1,0,0);elselockf(1,1,0);for (i=0;i500;i+) printf(“children%dn”,i);lockf(1,0,0);结果:大致与程序 1 的执行结果一样,但不会消灭同一组字符串间隔消灭的情形。分析:由于 lockf( )函数锁定标准输出设备屏幕,故不行能消灭一个字符串序列还没有显示完,就被其他进程抢占输出的情形;各组
36、字符串的输出挨次可能不同,但必定连续输出500 次。四、试验软硬件环境硬件要求:P4 2.0G 1G 内存 60G 硬盘以上电脑软件要求:C、C+编程环境,Java 编程环境五、试验步骤试验每人单独完成,独立设计算法,用C、C+或Java 实现。六、试验考核方法提交程序包含说明和注释,程序产生的数据文件 Inputdata,程序处理后的数据文件 OutputData,以上都是电子文档;另外每个同学分别提交纸质的试验报告,具体介绍试验中的工作,遇到的问题,解决方法,试验后的体会和设想。七、附:思考题(1) 系统是怎样创立进程的?(2) 当首次调用创立进程时,其入口在哪里?(3) 进程的互斥是如何
37、实现的?试验四 进程通信一、试验目的与要求(1) 了解和生疏管道通信机制;(2) 理解消息通信机制的工作原理。二、预备学问(1) 阅读Linux 的msg.c、sem.c、shm.c 等源码文件;(2) 生疏Linux 的几种通信机制的工作原理。三、试验内容(1) 进程的管道通信任务:编制程序,实现进程的管道通信:利用系统调用pipe( )创立管道,利用write( )向管道写入消息,利用read( )从管道读出消息。两个子进程p1 和 p2 分别向管道各写一句话: Child1 is sending message!Child2 is sending message!而父进程则从管道分别读出
38、来自两个子进程的消息并显示。程序:# include # include # include main( )int fd2,pid1,pid2;char OutPipe100,InPipe100;pipe(fd);/*创立管道*/while (pid1=fork( )= =-1);/*创立子进程 1*/ if (pid1= =0)/*子进程 1 创立成功*/lockf(fd1,1,0);/*锁定管道写入端*/ sprintf(OutPipe,”Child1 is sending message!”);/*定义发送缓冲区*/ write(fd1,OutPipe,50);/*写入管道*/sleep
39、(5);lockf(fd1,0,0);/*释放管道写入端*/exit(0);/*子进程终止*/elsewhile (pid2=fork( )= =-1); if (pid2= =0)lockf(fd1,1,0);sprintf(OutPipe,”Child2 is sending message!”);write(fd1,OutPipe,50); sleep(5); lockf(fd1,0,0); exit(0);elsewait(0);/*等待子进程终止*/read(fd0,InPipe,50);/*从管道读出端读消息到接收缓冲区*/ printf(“%sn”,InPipe);/*输出读到的
40、消息*/ wait(0);read(fd0,InPipe,50); printf(“%sn”,InPipe); exit(0);结果:Child1 is sending message! Child2 is sending message! 分析:由于对管道的写入端加锁,当子进程 p1 写入消息时子进程p2 不行能同时写入;由于对管道的读出端加锁,当父进程未读完来自子进程p1 的消息时不行能读来自p2 的消息。(2) 进程的消息通信机制任务:编制程序,使用系统调用msgget( )、msgsnd( )、msgrev( )、msgctl( )对大小为 1kb的消息进展发送和接收。父进程中创立两个
41、子进程SERVER 和 CLIENT 进展通信;SERVER 端建立一个key 为 75 的消息队列,等待其他进程发来的消息。当遇到类型为1 的消息时,则作为完毕信号,取消该队列并退出SERVER;SERVER 每接收到一个消息后显示一句“(server)received”。CLIENT 端使用 key 为 75 的消息队列,先后发送类型从 10 到 1 的消息,然后退出;最终一个消息就是 SERVER 端需要的完毕信号; CLIENT 每发送一条消息后显示一句“(client)sent”。父进程在SERVER 和CLIENT 均退出后完毕。程序:# include# include # in
42、clude# include# define MSGKEY 75/*定义关键词 MEGKEY*/struct msgform/*消息构造*/long mtype;char mtext1030;msgint msgqid,i; void CLIENT( )int i; msgqid=msgget(MSGKEY,0777); for (i=10;i=1;i-)msg.mtype=i;printf(“(client)sentn”);msgsnd(msgqid,&msg,1024,0); /*发送消息 msg 进入消息队列msgqid*/exit(0); void SERVER( )msgqid=ms
43、gget(MSGKEY,0777|IPC_CREAT); /*由关键词获得消息队列*/ domsgrcv(msgdid,&msg,1030,0,0);/*从消息队列接收消息 msg*/printf(“(server)receiven”);while (msg.mtype!=1);/*消息类型为 1 时释放队列*/ msgctl(msgqid,IPC_RMID,0);exit(0);main( )while(i=fork)=-1);if (!i) SERVER;while(i=fork)=-1);if (!i) CLIENT;wait(0);wait(0);结果:抱负的结果应当是: CLIENT 每发送一条消息, SERVER 马上接收该消息,屏