操作系统课程实验及设计.doc

上传人:小小飞 文档编号:5022787 上传时间:2020-01-29 格式:DOC 页数:24 大小:197.50KB
返回 下载 相关 举报
操作系统课程实验及设计.doc_第1页
第1页 / 共24页
操作系统课程实验及设计.doc_第2页
第2页 / 共24页
操作系统课程实验及设计.doc_第3页
第3页 / 共24页
操作系统课程实验及设计.doc_第4页
第4页 / 共24页
操作系统课程实验及设计.doc_第5页
第5页 / 共24页
点击查看更多>>
资源描述

《操作系统课程实验及设计.doc》由会员分享,可在线阅读,更多相关《操作系统课程实验及设计.doc(24页珍藏版)》请在三一文库上搜索。

1、实验1 Windows的用户界面2实验2 虚拟机及Linux操作系统的安装3实验3 Linux程序设计基础4实验4 进程管理6附件一:Linux程序设计基础9附件二:fork()函数18附件三:实验四补充21实验1 Windows的用户界面 实验目的熟悉Windows的GUI界面和命令控制界面学习并熟悉Windows的命令行解释器及常用命令理解批处理文件及批处理文件的使用实验准备及预习熟悉Windows的命令解释器及字符用户界面上网查阅Windows的常用命令及使用实验内容1)批处理文件的创建切换到命令提示符状态下,使用命令edit打开字符界面的编辑器,创建批处理文件exam.bat,内容如下

2、所示。理解批处理文件文件中各行代码的含义,保存退出编辑器。echo offmkdir d:mytestecho onpause2)批处理文件的执行在命令提示符下输入exam.bat来执行批处理,文件中的命令将顺序执行,并通过屏幕显示执行效果。3)批处理文件实验设计创建文件exam1.bat、exam2.bat及exam3.bat,了解输入输出重定向、批处理文件中的参数及批处理文件间互调用等功能。文件内容如下:exam1.bat:echo offmkdir e:testcall exam2.bat e:test call exam3.bat e:testecho call ok!Pauseexa

3、m 2.bat: echo offmem %1meminfo.txtecho generate memoryinfo ok!exam3.bat:echo offtype %1*.txtecho type ok!在命令提示符下输入exam1.bat来执行批处理,文件中的命令将顺序执行,并通过屏幕显示执行效果。实验2 虚拟机及Linux操作系统的安装 实验目的熟悉虚拟机及Linux操作系统的基本概念在VMware workstation上创建一台虚拟机,并安装Linux操作系统熟悉RedHat Linux的基本操作界面实验内容1、下载并安装VMware workstation2、在VMware w

4、orkstation上创建一台虚拟机3、在虚拟机上安装Linux操作系统4、熟悉RedHat Linux的基本操作界面实验3 Linux程序设计基础实验目的了解并熟悉Linux下C程序编写的过程能在Linux下实现简单的C程序熟悉并体会进程及进程控制的基本概念,及它们在Linux操作系统中的实现利用Linux实现进程的创建和控制实验准备及预习熟悉Linux操作系统的用户界面阅读讲义Linux程序设计基础,了解C编程的步骤等必须具备的基础知识。详见附件一熟悉进程及进程控制的有关概念查找并熟悉系统调用函数fork(),详见附件二实验内容1、简单C程序的编程实现。1)使用Linux自带的文字编辑器录

5、入hello.c的源代码,并保存为hello.c文件。注意存储路径。#include void main() printf(Hello World!n); 2)编译、链接源程序文件hello.c(在命令提示符状态下)。gcc -o hello hello.c3)运行源程序文件,查看程序输出是否正确。./hello2、进程创建及fork()函数的使用:分析并实现下列两个源程序。#include int main()int child = 0; child = fork();if (child = 0)printf(childn);else if (child 0)printf(parentn);

6、return 0;void main()int i;if ( fork() = 0 ) /* 子进程程序 */for ( i = 1; i 1000; i + ) printf(This is child processn);else /* 父进程程序*/for ( i = 1; i 1000; i + ) printf(This is process processn);实验4 进程管理实验目的加深对进程概念的理解,明确进程和程序的区别进一步认识并发执行的实质分析进程竞争资源的现象,学习解决进程互斥的方法了解Linux系统中进程通信的基本原理实验准备及预习阅读讲义实验四补充,理解有关函数功能

7、及语法,详见附件三实验内容1、进程控制下面给出的代码使用系统调用for()创建了两个子进程。观察程序执行时屏幕上给出的输出现象,并分析原因。#include int main()int p1, p2, i; while(p1=fork()=-1);if(p1=0)for(i=0;i25;i+) printf(“child %dn”, p1);getchar();for(i=0;i25;i+) printf(“child %dn”, p1); else while(p2=fork()=-1);if(p2=0)for(i=0;i25;i+) printf(“child %dn”, p2);getc

8、har();for(i=0;i25;i+) printf(“child %dn”, p2);elsefor(i=0;i25;i+) printf(“parentn”);getchar();for(i=0;i25;i+) printf(“parentn”);return 0;2、编写一段程序,使其实现进程的软中断通信,要求:使用系统调用fork()创建两个自进程,再使用系统调用signal()让父进程捕捉键盘上来的中断信号(即按下Del键);捕捉到中断信号后父进程用系统调用kill()向两个子进程发出终止信号,子进程捕捉到终止信号后输出“child process n is killed by

9、parent!”并终止。父进程等待两个子进程终止后,输出如下信息后结束运行:“parent process is killed!”。#include #include #include void waiting();void stop();int wait_mark;main()int p1,p2;while(p1=fork()=-1);if(p10)while(p2=fork()=-1);if(p20)printf(“parentn”);wait_mark=1;signal(SIGINT, stop);waiting();kill(p1,16);kill(p2,17);wait(0);wai

10、t(0);printf(“parent process is killed!n”);exit(0);elseprintf(“p2n”);wait_mark=1;signal(17,stop);waiting();lockf(stdout,1,0);printf(“child process2 is killed by parent!n”);lockf(stdout,0,0);exit(0);elseprintf(“p1n”);wait_mark=1;signal(16,stop);waiting();lockf(stdout,1,0);printf(“child process1 is kil

11、led by parent!n”);lockf(stdout,0,0);exit(0);void waiting()while(wait_mark!=0);void stop()wait_mark=0;3、编制一段程序,实现进程的管道通信。使用系统调用pipe()建立一条管道线,两个子进程p1和p2分别向管道各写一句话:child1 is sending a message!Child2 is sending a message!父进程则从管道中读出来自子进程的信息,并显示在屏幕上。#include #include #include int pid1,pid2;main()int fd2;c

12、har OutPipe100, InPipe100;pipe(fd);while(pid1=fork()=-1);if(pid1=0)printf(“p1n”);lockf(fd1,1,0);sprintf(OutPipe, “child1 is sending a message!”);write(fd1, OutPipe, 50);sleep(1);lockf(fd1,0,0);exit(0);elsewhile(pid2=fork()=-1);if(pid2=0)printf(“p2n”);lockf(fd1,1,0);sprintf(OutPipe, “child1 is sendin

13、g a message!”);write(fd1, OutPipe, 50);sleep(1);lockf(fd1,0,0);exit(0);elseprintf(“parentn”);wait(0);read(fd0,InPipe,50);printf(“%sn”,InPipe);wait(0);read(fd0,InPipe,50);printf(“%sn”,InPipe);exit(0);附件一:Linux程序设计基础Linux程序设计基础首先希望能够向读者重申Linux(Unix)的程序设计风格。虽然在任何平台上用C语言编程在很多方面都是一样的,但Linux(Unix)开发者对编程和系

14、统开发确有其独特观点,典型的Linux(Unix)程序和系统具有如下特点:1、简单性:许多很有用的Unix工具是非常简单的,因此也是很小并易于理解的。“小而简单”的理念是值得提倡的,因为大而复杂的程序注定会包含更大、更复杂的bug,而程序调试是所有人都想避免的。2、集中性:通常让一个程序很好地执行一项任务要好过把所有功能都不加选择地堆在一起。功能复杂、肿胀的程序难于使用和维护,而目标单一的程序更容易随着更好的算法或界面被开发出来而得到改进。当新的用户需求出现时,Unix通常是把小工具组合起来以完成更复杂的任务,而不是试图将用户可能期望的所有功能都放在一个大程序里。3、可重用组件:将应用程序的核

15、心实现为库。具有简单而灵活的编程接口、文档齐备的库可以帮助其他人开发出同类程序,或者把这些技术应用到新的应用领域。dbm库就是一个例子,它是一组可重用的函数,而不是单一的数据库管理程序。4、过滤器:许多Unix应用程序可用作过滤器,即它们对输入进行转换并产生输出。Unix提供了某种机制,使Unix程序能以新颖方式组合,以开发出相当复杂的应用程序。5、开放的文件格式:比较成功并流行的Unix程序都使用纯ASCII码文本文件作为配置文件和数据文件,因此用户可以用标准工具修改和搜索配置项,并可开发出在数据文件上执行新功能的新工具。ctags源代码交叉引用系统就是一个好例子,它把符号位置信息以适合于搜

16、索程序使用的正则表达式的形式记录下来。6、灵活性:你不能期待用户都能正确地使用你的程序,所以编程时要尽量考虑到程序的灵活性;尽量避免对字段长度或记录数目进行人为限制。这样你编写的程序既能在单机上运行也能跨网络运行。永远不要认为你知道用户想做的一切事。许多人认为Linux程序设计就是用C语言编程。的确Unix最初是用C语言编写的,Unix的大多数应用程序也是用C语言编写的,但C语言并不是Linux/Unix程序员的唯一选择。对Linux系统来说有各种各样的编程语言可供选用,其中许多是免费的。下面列出了Linux程序员可用的部分编程语言。Ada C C+Eiffel Forth FortranIc

17、on JavaJavaScriptLisp Modula 2Modula 3Oberon Objective C PascalPerl PostScript PrologPython Scheme SmalltalkSQL Tcl/TkBourne Shell 这里我们将集中精力从C语言程序员的视角探究Linux编程接口。1、Linux程序Linux应用程序表现为两种特殊类型的文件:可执行文件和脚本文件。可执行文件是计算机可以直接运行的程序,它们相当于Windows中的*.exe文件。脚本文件是一组指令的集合,这些指令将由另一个程序(即解释器)来执行,它们相当于Windows中的*.bat文件

18、、*.cmd文件或解释执行的BASIC程序。Linux并不要求可执行程序或脚本具有特殊的文件名或扩展名,而是通过文件系统属性来指明一个文件是否为可执行程序。Linux中的编译程序与脚本在用户级别上本质并无区别。登录Linux系统时,我们与一个shell程序(通常是bash)进行交互,它像Windows中的命令提示窗口一样运行程序。它在一组给定目录路径下按照给出的程序名搜索与之同名的文件。搜索目录存储在shell变量PATH里,这一点与Windows也很类似。搜索路径(也可以对这个路径进行添加)由系统管理员配置,通常包含一些存储系统程序的标准路径,其中包括:l /bin:二进制文件目录,用于存放

19、启动系统时用到的二进制文件。l /usr/bin:用户二进制文件目录,用于存放用户使用的标准程序。l /usr/local/bin:本地二进制文件目录,用于存放特定软件安装的程序。系统管理员(例如root用户)登录后使用的PATH变量还包含存放系统管理程序的目录,如/sbin和/usr/sbin。注意,Linux像Unix一样,使用冒号(:)分隔PATH变量里的条目,而不是像MS-DOS和Windows使用分号(;);Linux用正斜线(/)分隔文件名里的目录名,而不是像Windows那样用反斜线()。2、C语言编译器在POSIX兼容的系统中,C语言编译器被称为c89。历史上,C语言编译器被简

20、称为cc。许多年来,不同厂商销售的类UNIX系统中所带的C语言编译器均包含不同的功能和选项,但它们一般都称为cc。在准备起草POSIX标准时,事实上已经不可能制订出兼容所有厂商的标准cc命令了。于是,POSIX委员会决定为C语言编译器创建新的标准命令,这就是c89。只要使用这个命令,则在任何机器上,它的编译选项都相同。Linux系统尽量实现这些标准。在Linux系统中,你会发现c89、cc和gcc这些命令全部或部分地指向系统的C语言编译器,通常是GNU C编译器,或者简称gcc。在Unix系统中,C语言编译器几乎总被称为cc。在本书中,我们将使用gcc,这是因为它随Linux的发行版一起提供,

21、并且它支持ANSI C的标准语法。实验:第一个Linux C语言程序我们通过编写、编译和运行我们的第一个Linux程序来开始Linux的C语言程序开发。还是从最有名的HelloWorld程序开始吧。(1) 下面是文件hello.c的源代码,你可以使用Linux自带的文字编辑器完成代码录入,并保存为*.c文件。#include #include void main() printf(Hello World!n); (2) 编译、链接源程序文件hello.c。gcc -o hello hello.c(3) 运行源程序文件./hello调用GNU C语言编译器(在Linux中大多数情况下用cc也可以

22、)将我们的C语言源代码转换为可执行文件hello。运行这个程序,打印出欢迎信息。因为这是我们的第一个程序,有些问题先指出来:hello程序很可能在你的主目录中。如果PATH变量不包含指向你的主目录的条目,shell就找不到hello程序。更进一步,如果PATH变量中的目录包含另一个名为hello的程序,就会执行那个程序。如果PATH中这样的目录出现在你的主目录之前,也会发生这种情况。为了避免这种潜在的问题,我们在程序名前指定文件存储在当前目录./中,./特别指示shell去执行当前目录下给定名称的程序。如果缺省-o name选项(告诉编译器将可执行程序放在何处),编译器将把程序放在一个名为a.

23、out的文件里(a.out的含义是assembler output,即汇编输出)。如果你确信编译了一个程序但又找不到它,别忘了看看有没有a.out文件。3、开发系统导引对Linux开发人员来说,了解软件工具和开发资源在系统中存放的位置是很重要的。以下几节将对一些重要的目录和文件做简单的介绍。1)应用程序应用程序通常存放在系统为之保留的特定目录中。系统为正常使用提供的程序,包括用于程序开发的工具,都可在目录/usr/bin中找到;系统管理员为某个特定的主机或本地网络添加的程序通常可在目录/usr/local/bin或/opt中找到。系统管理员一般喜欢使用/usr/local目录,因为它分离了厂商

24、提供及后续添加的文件与系统本身提供的应用程序。保持/usr目录的这种组织方法的好处是:当你需要升级操作系统时,只需保留目录/usr/local里的内容。建议在/usr/local目录结构下编译、运行自己的程序,并访问必需的文件。其他一些功能特性和编程系统都可能有其自己的目录结构和程序目录。其中最主要的就是X视窗系统,它通常安装在/usr/X11目录下,可选的安装位置还有用于修订版第6版的/usr/X11R6目录,XFree社团发布的用于Intel处理器芯片的各种XFree86变体也安装在这里,许多Linux发行版也用这个目录安装X视窗系统。GNU编译系统的驱动程序gcc(在本章前面的编程示例中

25、用过)一般位于/usr/bin或/usr/local/bin目录中,但它会从其他位置运行各种编译器支持的应用程序。这个位置是在编译编译器本身时指定的,并且随主机类型的不同而不同。对Linux系统来说,这个位置可能是/usr/lib/gcc-lib/目录下的一个版本特定的子目录,GNU C/C+编译器的各个工具和GNU专用的头文件都保存在这里。2)头文件用C语言及其他语言进行程序设计时,通常利用头文件来提供对常量的定义和对系统及库函数调用的声明。这些头文件几乎总是在/usr/include目录及其子目录下。其他编程系统也有各自的include文件,并将其存储在可被相应编译器自动搜索到的目录里。例

26、如X视窗系统的/usr/include/X11目录和GNU C+的/usr/include/g+目录。调用C语言编译器时,我们可以使用-I标志来包含保存在子目录或非标准位置中的include文件。例如:gcc -I/usr/openwin/include fred.c标志-I指示编译器不仅在标准位置,也在/usr/openwin/include目录中查找程序fred.c中包含的头文件。请参看C语言编译器的使用手册(man gcc)以了解更多细节。用grep命令来搜索包含某些特定定义和函数原型的头文件是很方便的。假设我们想知道用来返回程序退出状态的#define定义的名字,就简单地切换到/usr

27、/include目录下,然后用grep命令搜索可能的名字部分,如下所示:grep命令在当前目录下的所有以.h结尾的文件中搜索字符串EXIT_。在本例中,它在stdlib.h文件中找到了我们需要的定义。3)库文件库是一组预先编译好的函数的集合,这些函数都是按照可重用的原则编写的,通常由一组相互关联的函数组成并执行某项常见的任务。比如屏幕处理函数库(curses和ncurses库)和数据库访问例程(dbm库)。标准系统库文件一般存储在/lib和/usr/lib目录中。C语言编译器(或更确切地说是链接程序)需要知道要搜索哪些库文件,默认情况下,它只搜索标准C语言库。这是从那个计算机速度还很慢而且CP

28、U运行周期还很昂贵的时代遗留下来的问题。仅把库文件放在标准目录中,然后希望编译器找到它是不够的,库文件必须遵循特定的命名规范并且需要在命令行中明确指定。库文件的名字总是以lib开头,随后的部分指明这是什么库(例如,c代表C语言库,m代表数学库)。文件名的最后部分以后缀的形式给出库文件的类型:*.a代表传统的静态函数库。* .so代表共享函数库函数库通常以静态库和共享库两种格式存在,可用ls /usr/lib命令查看。我们可以通过给出完整的路径名或用-l标志来指示编译器要搜索的库文件。例如:gcc -o fred fred.c /usr/lib/libm.a这条命令指示编译器编译文件fred.c

29、,将编译产生的程序文件命名为fred,并且除搜索标准的C语言函数库外,还搜索数学库以解决函数引用问题。下面的命令也能产生类似的结果:gcc -o fred fred.c lm-lm(在字母l和m之间没有空格)是简写方式(简写在UNIX环境里很有用),它代表的是标准库目录(本例中是/usr/lib)中名为libm.a的函数库。-lm标志的另一个好处是如果有共享库,编译器会自动选择共享库。虽然库文件和头文件一样,通常都保存在标准位置,但我们也可以通过-L(大写字母)标志为编译器增加库的搜索路径。例如:gcc -o x11fred -L/usr/openwin/lib x11fred.c -lX11

30、这条命令用/usr/openwin/lib目录中的libX11库版本来编译和链接程序x11fred。4)静态库函数库最简单的形式是一组处于“准备好使用”状态的目标文件。当程序需要使用函数库中的某个函数时,它包含一个声明该函数的头文件。编译器和链接器负责将程序代码和函数库结合在一起以组成一个单独的可执行文件。我们必须用-l选项指明除标准C语言运行库外还需使用的库。静态库,也称作归档文件(archive),按惯例它们的文件名都以.a结尾。比如,标准C语言函数库/usr/lib/libc.a和X11函数库/usr/X11/lib/libX11.a。我们可以容易地创建和维护自己的静态库,只要使用ar(

31、代表archive,即建立归档文件)程序和gcc c命令对函数分别进行编译。我们应该尽可能把函数分别保存到不同的源文件中。如果函数需要访问公共数据,我们则把它们放在同一个源文件中并使用在该文件中声明的静态变量。实验:静态库下面我们来创建一个小型函数库,它包含两个函数,然后在一个示例程序中调用其中一个函数。这两个函数分别是fred和bill,它们只打印欢迎信息。(1) 为两个函数分别创建各自的源文件(将它们分别命名为fred.c和bill.c)。第一个源文件:第二个源文件:(2) 分别编译这些函数,产生要包含在库文件中的目标文件。通过调用带有-c选项的C 语言编译器来实现,-c选项会阻止编译器创

32、建一个完整的程序。gcc -c bill.c fred.cls *.o屏幕显示将包含编译的两个文件bill.o和 fred.o(3) 现在编写一个调用bill函数的程序。首先,为我们的库文件创建一个头文件。这个头文件将声明我们的库文件中的函数,它能被所有希望使用我们创建的库文件的应用程序所包含。把头文件包含在源文件fred.c和bill.c中是有益的,它将帮助编译器发现所有错误。(4) 调用程序(program.c)非常简单。它包含库的头文件并且调用库中的一个函数。(5) 现在,我们来编译并测试这个程序。我们暂时为编译器显式指定目标文件,然后要求编译器编译我们的文件并将其与预先编译好的目标模块

33、bill.o链接。(6) 现在,创建并使用一个库文件。我们用ar程序创建一个归档文件并将目标文件添加进去。这个程序之所以称为ar,是因为它将若干单独的文件归并到一个大的文件中以创建归档文件或集合。注意,我们也可以用ar程序来创建任何类型文件的归档文件(与许多UNIX工具一样,ar是一个通用工具)。(7) 库文件创建好了,两个目标文件也已添加。在某些系统,尤其是从Berkeley UNIX衍生的系统中,要想成功地使用函数库,还需要为函数库生成一个内容表。我们通过ranlib命令来完成这一工作。在Linux中,如果我们使用的是GNU的软件开发工具,这一步就不是必需的(但做了也无妨)。我们的函数库现

34、在即可使用了。我们可以在编译器命令行的文件列表中添加该库文件以创建我们的程序,如下所示:也可以用-l选项来访问我们的函数库,但是因为其未保存在标准位置,所以我们必须用-L选项来指示编译器在何处可以找到它,如下所示:-L.选项指示编译器在当前目录(.)中查找函数库。-lfoo选项指示编译器使用名为libfoo.a的函数库(或者名为libfoo.so的共享库,如果它存在的话)。要查看目标文件、函数库或可执行文件里包含的函数,我们可使用nm命令。如果我们查看program和libfoo.a,就会看到函数库libfoo.a中包含fred和bill两个函数,而program里只包含函数bill。创建程序

35、时,它只包含函数库中它实际需要的函数。虽然程序中的头文件包含函数库中所有函数的声明,但这并不将整个函数库包含在最终的程序中。如果你熟悉Windows软件开发,就会发现两者之间有许多相似之处,如下表所示。项 目UNIXWindows目标模块func.oFUNC.OBJ静态函数库lib.aLIB.LIB程序programPROGRAM.EXE5)共享库静态库的一个缺点是,当我们同时运行许多应用程序并且它们都使用来自同一个函数库的函数时,就会在内存中有同一函数的多份拷贝,在程序文件自身中也有多份同样的拷贝。这将消耗大量宝贵的内存和磁盘空间。许多UNIX系统和Linux支持共享库,它克服了上述不足。共

36、享库的保存位置与静态库是一样的,但共享库有不同的文件名后缀。在典型的Linux系统中,标准数学库的共享版本是/usr/lib/libm.so。程序使用共享库时,它的链接方式是这样的:它本身不再包含函数代码,而是引用运行时可访问的共享代码。当编译好的程序被装载到内存中执行时,函数引用被解析并产生对共享库的调用,如果有必要共享库才被加载到内存中。通过这种方法,系统可只保留共享库的一份拷贝并供许多应用程序同时使用,并且在磁盘上也仅保存一份。另一个好处是共享库的更新可以独立于依赖它的应用程序。文件/usr/lib/libm.so是对实际库文件修订版本(/usr/lib/libm.so.N,其中N代表主

37、版本号,在写作本书时它是6)的符号链接。Linux启动应用程序时,它会考虑应用程序需要的函数库版本,以防止新的主版本函数库致使旧的应用程序不能使用。4、获得帮助绝大多数Linux系统都为系统编程接口和标准工具提供了很好的文档。这是因为,从早期的UNIX系统开始,就鼓励程序员为他们的应用程序提供手册页。这些手册页可以通过电子形式获得,有时也会以印刷品的形式提供。man命令可用来访问在线手册页。这些手册页在质量和细节上千差万别。有些可能只是简单地让读者参考其他更详细的文档,而另外一些则给出了一个工具所支持的所有选项和命令的完整清单。无论是哪种情况,手册页都是一个好的起点。GNU软件和其他一些自由软

38、件还使用名为info的在线文档系统。你可以通过特殊的程序info或通过emacs编辑器中的info命令来在线浏览全部的文档。info系统的优点是,你可以通过链接和交叉引用来浏览文档并可直接跳转到相关的章节。对文档作者来说,info系统的优点是它的文件可以由排版印刷文档使用的同一个源文件自动生成。实验:手册页和info我们来看看GNU C语言编译器的文档。(1) 首先查看手册页。如果愿意,我们可以阅读编译器支持的各个选项的相关信息。这个例子中的手册页相当长,但它仍然只是GNU C(和C+)语言编译器整个文档中的一小部分。阅读手册页时,我们可以按空格键读下一页,按Enter键(或Return键,如

39、果你的键盘上是Return键的话)读下一行,按q键退出。(2) 为了获得更多关于GNU C语言编译器的信息,我们可以使用info命令。我们将看到一个很长的选项菜单,可以通过选择其中的选项在一个完全文本化的文档中四处移动。菜单项和层次化的页面布局允许我们浏览很大的文档。如果印在纸上的话,GNU C的文档有好几百页之多。当然,info系统也包含它自己的一个info形式的帮助页。如果按下Ctrl+H组合键,我们将看到一些帮助信息,其中包括如何使用info的指南。info程序在许多Linux的发行版里都有,它也可以安装在其他UNIX系统上。附件二:fork()函数fork函数对于没有接触过Unix/L

40、inux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值。fork函数是Unix系统最杰出的成就之一,它是七十年代UNIX早期的开发者经过长期在理论和实践上的艰苦探索后取得的成果,一方面,它使操作系统在进程管理上付出了最小的代价,另一方面,又为程序员提供了一个简洁明了的多进程方法。与DOS和早期的Windows不同,Unix/Linux系统是真正实现多任务操作的系统,可以说,不使用多进程编程,就不能算是真正的Linux环境下编程。多线程程序设计的概念早在六十年代就被提出,但直到八十年代中期,Unix系统中才引入多线程机制,如今,由于自身的许多优点,多线程编程已经得到了广泛

41、的应用。下面,我们将介绍在Linux下编写多进程和多线程程序的一些初步知识。多进程编程什么是一个进程?进程这个概念是针对系统而不是针对用户的,对用户来说,他面对的概念是程序。当用户敲入命令执行一个程序的时候,对系统而言,它将启动一个进程。但和程序不同的是,在这个进程中,系统可能需要再启动一个或多个进程来完成独立的多个任务。多进程编程的主要内容包括进程控制和进程间通信,在了解这些之前,我们先要简单知道进程的结构。Linux下进程的结构Linux下一个进程在内存里有三部分的数据,就是代码段、堆栈段和数据段。其实学过汇编语言的人一定知道,一般的CPU都有上述三种段寄存器,以方便操作系统的运行。这三个

42、部分也是构成一个完整的执行序列的必要的部分。代码段,顾名思义,就是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用相同的代码段。堆栈段存放的就是子程序的返回地址、子程序的参数以及程序的局部变量。而数据段则存放程序的全局变量,常数以及动态数据分配的数据空间(比如用malloc之类的函数取得的空间)。这其中有许多细节问题,这里限于篇幅就不多介绍了。系统如果同时运行数个相同的程序,它们之间就不能使用同一个堆栈段和数据段。Linux下的进程控制在传统的Unix环境下,有两个基本的操作用于创建和修改进程:函数fork( )用来创建一个新的进程,该进程几乎是当前进程的一个完

43、全拷贝;函数族exec( )用来启动另外的进程以取代当前运行的进程。Linux的进程控制和传统的Unix进程控制基本一致,只在一些细节的地方有些区别,例如在Linux系统中调用vfork和fork完全相同,而在有些版本的Unix系统中,vfork调用有不同的功能。不过这些差别几乎不影响我们大多数的编程。fork()函数fork()用于linux下创建进程。fork原型为:pid_t fork() ;返回值的意义如下:0:创建子进程,从子进程返回的id值0:从父进程返回的子进程id值-1:创建失败,通常在系统内存不够或者进程数已经达到上限时fork才会失败例1:#include int main

44、()int child = 0; child = fork();if (child = 0)printf(childn);else if (child 0)printf(parentn);return 0;fork()的作用:创建子进程,并从父进程的此处开始复制执行。执行代码child = fork()时,如果返回的是-1(即fork失败时), 则无输出;如果成功创建了进程,则从child = fork() 开始的代码都将会被子进程继承,一并继承的还有子进程的数据,因此子进程也会执行逻辑判断if (child = 0)。fork函数在子进程中调用时会返回0 ,以表示自己是一个子进程。 另外,fork函数在子进程中只是第一次运行时才会返回0 以表示自己的子进程身份, 而当第二次甚至更多次运行时则会创建新的属于自己的子进程。因此对父进程言,执行的是逻辑判断(child 0)时的输出语句printf(parentn);,而子进程执行逻辑判断(child = 0)时的输出语句printf(childn);。例2:这段程序演示了使用fork的基本框架:void main()int i;if ( fork()

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 研究报告 > 商业贸易


经营许可证编号:宁ICP备18001539号-1