操作系统实验指导书青岛理工大学计算机工程学院二零一一年九月1一、课程编号:071235二、适用专业:计算机科学与技术专业、网络工程专业、软件工程专业三、实验个数与学时:4个实验,8学时四、《操作系统实验》的目的《操作系统》是一门重要的专业基础课,是涉及较多硬件知识的计算机系统软件课程。在计算机软硬件课程的设置上,它起着承上启下的作用。操作系统对计算机系统资源实施管理,是所有其他软件与计算机硬件的唯一接口,所有用户在使用计算机时都要得到操作系统提供的服务。操作系统实验的主要任务是让学生掌握常用操作系统的安装方法,了解操作系统进程管理的基本内容,通过实验演示了解操作系统是如何进行进程管理的,为后期操作系统的课程设计奠定基础。五、实验平台在虚拟机Vmware或者VirtualBox上的Ubuntu11.102实验1安装Linux操作系统一、实验目的在虚拟机Vmware或者VirtualBox上安装Unbuntu11.10操作系统,后续实验都将在此环境上进行。通过实验,要求:1、掌握在虚拟机上安装操作系统的方法;2、学会安装Linux系统;3、学会启动Linux系统;4、学会在宿主机WindowsXP操作系统下,与虚拟机上安排的Ubuntu共享文件的方法。二、实验内容1、把ubuntu安装至虚拟机上。加载安装ubuntu操作系统的ISOIMG文件启动ubuntu虚拟机按提示分阶段装入系统2、在Windows下通过网络磁盘来访问ubuntu共享文件夹在虚拟系统Ubuntu下新建一个文件夹,右击该文件夹,选择属性,共享,启用“共享此目录”,并允许他人在此共享里写数据。注:共享时需要Samba的支持,系统会提示安装。安装完成Samba后,需要重启ubuntu才能生效。此时回到XP时可在网上邻居里看到一个***-desktopserver(Samba,Ubuntu)的共享目录。返回WindowsXP系统,右击“网上邻居”,选择“映射网络驱动器”,3在“浏览”里找到刚才在Ubuntu下共享的文件夹,选择后完成映射,这时打开“我的电脑”会发现多了一个“网络驱动器”,如同我们的硬盘一样。4这时你可以在XP系统里复制几个文件到相应的网络驱动器,然后进入Ubuntu系统,就能看到我们刚才复制的文件了;当然,我们也可以往ubuntu共享文件夹里放文件,在XP系统使用。注:在创建文件共享的时候,注意主机的网卡一定要打开,否则创建共享是不能成功的5实验2Linux系统中程序编辑、编译与调试工具一、实验目的1、熟悉使用Linux字符界面、窗口系统的常用命令。2、熟悉运用Linux常用的编程工具。3、掌握在Linux操作系统环境上编辑、编译、调试、运行一个C语言程序的全过程。二、实验内容1、熟悉开机后登录Linux系统和退出系统的过程;2、掌握一种Linux的编辑器,特别是字符界面的vi工具的使用(详见VI简易使用手栅);3、掌握GCC编译器的基本用法(详见GCC使用手册及常用命令行);4、掌握GDB调试程序的方法(详见GDB调试程序手册)。要求在实验报告上完整地进行一个数据结构中c程序的调试,源代码不能少于50行。6实验3进程并发与同步一、实验目的1、加深对进程概念的理解,区分进程并发执行与串行执行;2、掌握进程并发执行的原理,理解进程并发执行的特点;3、了解fork()系统调用的返回值,掌握用fork()创建进程的方法;熟悉wait、exit等系统调用;4、能利用相应的系统调用实现进程树与进程间的同步。二、实验内容1、编写一C语言程序,实现在程序运行时通过系统调用fork()创建两个子进程,使父、子三进程并发执行,父亲进程执行时屏幕显示“Iamfather”,儿子进程执行时屏幕显示“Iamson”,女儿进程执行时屏幕显示“Iamdaughter”。要求多次连续反复运行这个程序,观察屏幕显示结果的顺序,直至出现不一样的情况为止。要求有运行结果截图与结果分析2、连续4个fork()的进程家族树,family1-1.c程序清单如下:#includestdio.hmain(){fork();fork();fork();fork();printf(“A\n”);}请根据程序运行结果,画出进程家族树,并分析原因。3、修改程序1,在父、子进程中分别使用wait、exit等系统调用“实现”其同步推进,父进程必须等待儿子进程与女儿进程结束,才可以输出消息。写出相应的同步控制,并分析运行结果。4、创建一个子进程,并给它加载程序,其功能是调用键盘命令“ls-l”,已知该键盘命令的路径与文件名为:/bin/ls。父进程创建子进程,并加载./child2程序。写出相应的程序代码并分析程序运行结果。三、系统调用创建子进程系统调用:fork()格式intfork();返回值=0创建成功,从子进程返回0创建成功,从父进程返回,其值为子进程的PID号=-1创建失败子进程创建时操作系统的工作:检查同时运行的进程数目,若超过系统设定值,则创建失败,返回-1;为子进程分配进程控制块task_struct结构,并赋予唯一进程标识符pid;子进程继承父进程打开的所有文件及资源,对父进程的当前目录和所有已打开系统文件7表项中的引用记数加1;为子进程创建进程映像:创建子进程映像静态部分:复制父进程映像静态部分创建子进程映像动态部分:初始化task_struct结构结束创建,置子进程为内存就绪状态,插入就绪队列,作为一个独立的进程被系统调度。若调用进程(父进程)返回,则返回创建的子进程标识符pid值(此时返回值0);若子进程被调度执行,则将其U区计时字段初始化然后返回(此时返回值=0)。进程睡眠系统调用:sleep()格式sleep(n);参数n表示延时的秒数功能进程睡眠n秒进程终止系统调用:exit(status)格式voidexit(intstatus);参数status是子进程向父进程发送的终止信息,父进程使用wait()系统调用来接收这个信息头文件#includestdlib.h功能将进程置僵死状态释放其所占有的资源向父进程发本进程死信号,并发送信息status给父进程,将自己及自己的子进程运行CPU的时间总和留待父进程使用wait()收集子进程终止时操作系统做以下工作:关闭软中断:因为进程即将终止而不再处理任何软中断信号;回收资源:关闭所有已打开文件,释放进程所有的区及相应内存,释放当前目录及修改根目录的索引节点;写记帐信息:将进程在运行过程中所产生的记帐数据(其中包括进程运行时的各种统计信息)记录到一个全局记帐文件中;置该进程为僵死状态:向父进程发送子进程死的软中断信号,将终止信息status送到指定的存储单元中;转进程调度:因为此时CPU已经被释放,需要由进程调度进行CPU再分配。父进程等待子进程终止系统调用:wait()与waitpid()格式1pid_twait([int*stat_addr,]0);参数*stat_addr中存放exit()所发来终止信号stat的值。返回值=0表示有子进程终止,其值为终止子进程的pid号=-1表示无子进程终止头文件#includesys/wait.h#includesys/types.h8功能父进程使用它等待任意一个子进程终止,如果在执行wait()之前已经有一个子进程结束了,则对其做善后处理,并返回子进程的pid号,如果没有则返回-1,该进程阻塞,插入等待子进程终止的队列,当有子进程终止时被唤醒。在&stat_addr中保留了子进程僵死时的终止信息(不是返回值)。注意:一个wait()只能用来等待一个子进程终止,如果等待多个子进程终止则需要使用多个wait()。格式2pid_twaitpid(pid_tpid,int*stat_addr,intoptions);参数pid=0等待与父进程同组的子进程pid=-1,options=0等同于wait(),等待任意子进程pid0等待给定pid号的子进程功能等待指定pid的子进程终止说明:1)若父进程仅仅只是等待任意一个子进程结束,而不需要取子进程发来的信号,则可以简单地使用wait(0)。2)如果该进程没有创建自己的子进程就不能使用wait()或waitpid(),否则系统会返回一个出错信息。3)如果要取子进程执行exit()后所发来的终止信号stat,可以使用*stat来取该变量中的值,而不能使用wait()的返回值,因为wait()的返回值是该终止子进程的pid号。将指定的可执行文件加载到指定进程映像中,覆盖该进程中原有的程序系统调用:execl()、execle()、execlp()、execv()、execve()与execvp()功能将一个指定的程序装入调用它的进程的映像中,用这个可执行文件的副本去覆盖该进程的程序空间,从而改变调用进程的执行代码,使调用进程执行新引入的可执行程序(二进制代码文件)内核在响应这组系统调用后做以下工作:1)根据给出的路径名找到指定的可执行文件,检查该文件是否可执行,用户是否具有执行权限(该文件必须是编译连接后的二进制代码)。2)将该文件载入到调用它的进程映像中覆盖其原来的程序。3)为该程序的执行设置参数数组和环境变量。4)启动该进程进入新的程序入口点去执行。此组函数执行时,如果加载成功则直接执行,没有返回;若加载不成功则返回-1。格式1execv(file,argv)参数char*file指向文件全名(路径名/文件名)的指针char*argv[n]指向命令及参数的指针功能1)执行参数指定的命令或文件。2)用该命令或可执行文件的副本覆盖调用它的子进程的映像返回值=-1表示错误返回头文件#includeunistd.h格式2execl(“路径名/文件名”,0)说明功能、返回值、头文件均同格式1使用方法:1)事先准备好子进程要执行的程序,并将它编译连接成可执行文件,记下该文件的路径名和文件名。如果不带参数则可以直接使用execl(),带参数则使用execv()。2)在父进程创建子进程之前,在程序中事先定义子进程要执行的程序文件的文件标识符path9和参数数组argv[],其中的环境值可以用NULL取代。如果不带参数使用execl(),则这一步可以不做。3)创建子进程后,在子进程的分支中,如果不带参数使用execl(filepath,0),如果带参数则使用execv(filepath,argv)来实现用指定的程序filepath覆盖子进程映像中原有的程序。10实验4进程通信一、实验目的1、加深理解进程通信的方法与原理;2、掌握如何利用管道机制、消息缓冲队列、共享存储区机制进行进程间的通信。二、实验内容1、了解系统调用pipe()、msgget()、msgsnd()、msgrcv()、msgctl()、shmget()、shmat()、shmdt()、shmctl()的功能和实现过程。2、编写一C语言程序,使其用管道来实现父子进程间通信。子进程向父进程发送字符串“issendingamessagetoparent!”;父进程则从管道中读出子进程发来的消息,并将其显示到屏幕上,然后终止。3、运行该程序,观察、记录并简单分析其运行结果。