操作系统实验指导书Vmware版.docx
《操作系统实验指导书Vmware版.docx》由会员分享,可在线阅读,更多相关《操作系统实验指导书Vmware版.docx(18页珍藏版)》请在冰豆网上搜索。
操作系统实验指导书Vmware版
操作系统实验指导书
青岛理工大学计算机工程学院
二零一一年九月
一、课程编号:
071235
二、适用专业:
计算机科学与技术专业、网络工程专业、软件工程专业
三、实验个数与学时:
4个实验,8学时
四、《操作系统实验》的目的
《操作系统》是一门重要的专业基础课,是涉及较多硬件知识的计算机系统软件课程。
在计算机软硬件课程的设置上,它起着承上启下的作用。
操作系统对计算机系统资源实施管理,是所有其他软件与计算机硬件的唯一接口,所有用户在使用计算机时都要得到操作系统提供的服务。
操作系统实验的主要任务是让学生掌握常用操作系统的安装方法,了解操作系统进程管理的基本内容,通过实验演示了解操作系统是如何进行进程管理的,为后期操作系统的课程设计奠定基础。
五、实验平台
在虚拟机Vmware上的Ubuntu11.10
实验1安装Linux操作系统
一、实验目的
在虚拟机Vmware上安装Unbuntu11.10操作系统,后续实验都将在此环境上进行。
通过实验,要求:
1、掌握在虚拟机上安装操作系统的方法;
2、学会安装Linux系统;
3、学会启动Linux系统;
4、学会在宿主机WindowsXP操作系统下,与虚拟机上安装的Ubuntu共享文件的方法。
二、实验内容
1、把ubuntu安装至虚拟机上。
●加载安装ubuntu操作系统的ISOIMG文件
●启动ubuntu虚拟机
●按提示安装Ubuntu操作系统
2、通过VmwareTools实现Windows与ubuntu之间的文件共享
1)先在Windows下建个共享文件夹,暂时取名叫share;
2)然后进入VMwareWorkstation软件主界面的菜单项VM进行设置:
①VM->setting->options->sharedfolders;
②单击Add按钮进入AddSharedFolderWizard向导进行共享文件夹的设定;
③在Name文本框内输入你为共享文件夹起的名称,在Hostfolder文本框中选定你在Windows下创建的共享文件夹share;
④然后设定指定共享文件夹的属性,选择Enablethisshare选项。
⑤选择finish,这样就完成了虚拟机中共享文件夹的设定。
3)进入虚拟机的下拉菜单VM->InstallVMwareTools...,出现一个对话框,单击“install”按钮;(前提条件是已经运行了虚拟机下的一个客户操作系统,即虚拟机上安装的Ubuntu操作系统已经启动了,否则虚拟机的VM->InstallVMwareTools...菜单将是不可选的)。
4)安装完毕后会在Linux的桌面上出现一个名为“VMwareTools”的光盘图标;
5)然后进入mnt/cdrom,把里面那个叫“VMwareTools-5.5.0-18463.tar.gz”的文件拷贝到opt下;
6)然后进入shell,用cd命令进入到opt文件夹下;
7)在命令行输入:
tarzxvfVMwareTools-5.5.0-18463.tar.gz回车(进行解压);
8)再用cd命令进入到解压的文件里,在命令行输入:
./vmware-install.pl接着一路回车,就ok了。
9)等安装完毕后,可以查看mnt文件夹里面会多了一个叫“hgfs”的文件夹,这下面的文件夹里就可以放Windows与Linux需要共享的文件了。
VMwareTools-9.6.1-1378637.tar.gz
VMwareTools-9.6.1-1378637.tar.gz
实验2Linux系统中程序编辑、编译与调试工具
一、实验目的
1、熟悉使用Linux字符界面、窗口系统的常用命令。
2、熟悉运用Linux常用的编程工具。
3、掌握在Linux操作系统环境上编辑、编译、调试、运行一个C语言程序的全过程。
二、实验内容
1、熟悉开机后登录Linux系统和退出系统的过程;
2、掌握一种Linux的编辑器,特别是字符界面的vi工具的使用(详见VI简易使用手栅);
3、掌握GCC编译器的基本用法(详见GCC使用手册及常用命令行);
4、掌握GDB调试程序的方法(详见GDB调试程序手册)。
要求在实验报告上完整地进行一个数据结构中c程序的调试,源代码不能少于50行。
实验3进程并发与同步
一、实验目的
1、加深对进程概念的理解,区分进程并发执行与串行执行;
2、掌握进程并发执行的原理,理解进程并发执行的特点;
3、了解fork()系统调用的返回值,掌握用fork()创建进程的方法;熟悉wait、exit等系统调用;
4、能利用相应的系统调用实现进程树与进程间的同步。
二、实验内容
1、编写一C语言程序,实现在程序运行时通过系统调用fork()创建两个子进程,使父、子三进程并发执行,父亲进程执行时屏幕显示“Iamfather”,儿子进程执行时屏幕显示“Iamson”,女儿进程执行时屏幕显示“Iamdaughter”。
要求多次连续反复运行这个程序,观察屏幕显示结果的顺序,直至出现不一样的情况为止。
要求有运行结果截图与结果分析
2、连续4个fork()的进程家族树,family1-1.c程序清单如下:
#include
main()
{
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;
✧子进程继承父进程打开的所有文件及资源,对父进程的当前目录和所有已打开系统文件表项中的引用记数加1;
✧为子进程创建进程映像:
⏹创建子进程映像静态部分:
复制父进程映像静态部分
⏹创建子进程映像动态部分:
初始化task_struct结构
⏹结束创建,置子进程为内存就绪状态,插入就绪队列,作为一个独立的进程被系统调度。
✧若调用进程(父进程)返回,则返回创建的子进程标识符pid值(此时返回值>0);
✧若子进程被调度执行,则将其U区计时字段初始化然后返回(此时返回值=0)。
进程睡眠系统调用:
sleep()
格式
sleep(n);
参数
n表示延时的秒数
功能
进程睡眠n秒
进程终止系统调用:
exit(status)
格式
voidexit(intstatus);
参数
status是子进程向父进程发送的终止信息,父进程使用wait()系统调用来接收这个信息
头文件
#include
功能
将进程置僵死状态
释放其所占有的资源
向父进程发本进程死信号,并发送信息status给父进程,将自己及自己的子进程运行CPU的时间总和留待父进程使用wait()收集
子进程终止时操作系统做以下工作:
✧关闭软中断:
因为进程即将终止而不再处理任何软中断信号;
✧回收资源:
关闭所有已打开文件,释放进程所有的区及相应内存,释放当前目录及修改根目录的索引节点;
✧写记帐信息:
将进程在运行过程中所产生的记帐数据(其中包括进程运行时的各种统计信息)记录到一个全局记帐文件中;
✧置该进程为僵死状态:
向父进程发送子进程死的软中断信号,将终止信息status送到指定的存储单元中;
✧转进程调度:
因为此时CPU已经被释放,需要由进程调度进行CPU再分配。
父进程等待子进程终止系统调用:
wait()与waitpid()
格式1
pid_twait([int*stat_addr,]0);
参数
*stat_addr中存放exit()所发来终止信号stat的值。
返回值
>=0
表示有子进程终止,其值为终止子进程的pid号
=-1
表示无子进程终止
头文件
#include
#include
功能
父进程使用它等待任意一个子进程终止,如果在执行wait()之前已经有一个子进程结束了,则对其做善后处理,并返回子进程的pid号,如果没有则返回-1,该进程阻塞,插入等待子进程终止的队列,当有子进程终止时被唤醒。
在&stat_addr中保留了子进程僵死时的终止信息(不是返回值)。
注意:
一个wait()只能用来等待一个子进程终止,如果等待多个子进程终止则需要使用多个wait()。
格式2
pid_twaitpid(pid_tpid,int*stat_addr,intoptions);
参数
pid=0
等待与父进程同组的子进程
pid=-1,options=0
等同于wait(),等待任意子进程
pid>0
等待给定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。
格式1
execv(file,argv)
参数
char*file
指向文件全名(路径名/文件名)的指针
char*argv[n]
指向命令及参数的指针
功能
1)执行参数指定的命令或文件。
2)用该命令或可执行文件的副本覆盖调用它的子进程的映像
返回值
=-1
表示错误返回
头文件
#include
格式2
execl(“路径名/文件名”,0)
说明
功能、返回值、头文件均同格式1
使用方法:
1)事先准备好子进程要执行的程序,并将它编译连接成可执行文件,记下该文件的路径名和文件名。
如果不带参数则可以直接使用execl(),带参数则使用execv()。
2)在父进程创建子进程之前,在程序中事先定义子进程要执行的程序文件的文件标识符path和参数数组argv[],其中的环境值可以用NULL取代。
如果不带参数使用execl(),则这一步可以不做。
3)创建子进程后,在子进程的分支中,如果不带参数使用execl(filepath,0),如果带参数则使用execv(filepath,argv)来实现用指定的程序filepath覆盖子进程映像中原有的程序。
实验4进程通信
一、实验目的
1、加深理解进程通信的方法与原理;
2、掌握如何利用管道机制、消息缓冲队列、共享存储区机制进行进程间的通信。
二、实验内容
1、了解系统调用pipe()、msgget()、msgsnd()、msgrcv()、msgctl()、shmget()、shmat()、shmdt()、shmctl()的功能和实现过程。
2、编写一C语言程序,使其用管道来实现父子进程间通信。
子进程向父进程发送字符串“issendingamessagetoparent!
”;父进程则从管道中读出子进程发来的消息,并将其显示到屏幕上,然后终止。
3、运行该程序,观察、记录并简单分析其运行结果。
三、有名管道、无名管道系统调用
1、创建无名管道的系统调用
创建无名管道的系统调用:
pipe()
格式
intpipe(int管道名[2]);
返回值
0
正确返回
1
错误返回
参数说明
管道名[1]:
为写入端
管道名[2]:
为读出端
功能
创建一个管道名为指定名称的无名管道,以便于创建管道的进程及其子孙进程共享
头文件
include
●当进程向管道中写时,数据就复制不予考虑了共享的数据页;
●从管道中读时,字节从共享页中按照FIFO的顺序复制出来。
●当所有进程完成管道的操作后,管道的i结点和共享数据页被释放。
2、读写管道的系统调用
读写管道的系统调用:
write()、read()
格式
write(管道名[1],buf,size)
read(管道名[0],buf,size)
参数说明
buf:
程序中定义的字符型数组或缓冲区;
size:
读写的信息长度
说明
管道为临界资源,父子进程之间除了需要读写同步以外,在对管道进行读写操作时还需要互斥进入。
为了保证管道操作过程中不至于因为用户的疏忽而死锁,Linux采用以下措施来避免死锁:
●当进程因读或写等待时,要检查管道的另一端是否已经关闭,如果发现对方已经关闭则直接返回,不再等待。
●当进程关闭管道时,要检查管道的另一端是否正处于等待状态,如果是,则要先唤醒对方,然后再关闭管道。
●如果进程需要实现互斥,因为管道是文件,可以使用对文件上锁和开锁的系统调用。
3、文件上锁、开锁系统调用
文件上锁、开锁系统调用:
lockf()
格式
lockf(files,function,size)
参数说明
files
是需要加以封锁的文件描述符,此处可以是管道的读写端口
function
为1表示上锁,为0表示开锁
size
表示锁定或开销的字节数,其值为0则表示文件全部内容
4、命名管道创建系统调用
命名管道创建系统调用:
mkfifo()
格式
intmkfifo(constchar*pathname,mode_tmode);
功能
专门用于创建FIFO
参数说明
mode
权限值,如0777表示所有用户都可读、可写、可执行
返回值
正确返回0,错误返回-1.
头文件
#include
#include
mknod用于创建一般的设备文件
四、Linux消息缓冲通信的系统调用
1、创建一个消息队列或获取已存在消息队列的标识
创建消息队列/获取已存在消息队列的系统调用:
msgget()
命令格式
intmsgget(key_tkey,intmsgflag);
功能
创建标识为key值的消息队列或者获取已存在的消息队列的描述符msgid
返回值
正确返回该消息队列的描述符msgid;
错误返回-1。
语句格式
msgid=msgget(key,msgflag);
参数说明
msgqid
该系统调用返回的消息队列描述符,-1表示失败;
key
用户指定的消息队列标识符,为一正整数,其值可以由用户指定,如果使用IPC_PRIVATE则由系统产生key值;
flag
用户设置的标志或访问方式,其值由操作权限和控制命令进行或运算得到
头文件
#include
#include
操作允许权八进制数
操作允许权八进制数
用户可读0400
用户可写0200
小组可读0040
小组可写0020
其他可读0004
其他可写0002
控制命令值
IPC_CREAT(创建)0001000
2、发送一条消息到指定的消息队列
发送一条消息到指定的消息队列系统调用:
msgsnd()
命令格式
intmsgsnd(intmsgid,structmsgbuf*msgp,intsize,intflag);
功能
发送一个消息给指定描述符的消息队列。
将msgp所指向的msgbuf中的消息复制到消息数据结构并挂到指定消息队列尾,唤醒等待消息的进程
参数说明
msgqid
执行msgget()返回的消息队列的描述符
msgp
指向用户存储区的一个消息缓冲msgbuf的指针,在msgbuf中包含消息类型和消息正文
size
由msgp指向的数据结构中字符数组的长度(消息长度)
flag
规定当核心用尽内部空间时应执行的动作。
例如:
若在flag中设置了IPC_NOWAIT,则当消息队列中的字节数超过最大值msgsnd立即返回,否则msgsnd睡眠。
flag可置0。
头文件
#include
#include
3、从消息队列接收消息
从消息队列接收消息的系统调用:
msgrcv()
命令格式
intmsgrcv(intmsgid,structmsgbuf*msgp,intsize,inttype,intflag);
功能
从指定的消息队列接收一个消息。
将消息复制到msgp所指的msgbuf中,从消息队列中删除此消息,若消息未到则调用进程阻塞,并将该进程插入等待消息队列尾。
参数说明
msgid
消息队列描述符;
msgp
用来存放要接收消息的用户msgbuf的地址;
size
msgp中数据数组的大小;
type
用户要读取的消息类型
=0表示接收队列的第一个消息;
>0表示接收类型type的第一个消息;
<0表示接收小于或等于|type|的最低类型的第一个消息
flag
规定若该队列无消息,操作系统核心应当做什么,可设置为0.
头文件
#include
#include
4、对消息队列的操作
对消息队列操作的系统调用:
msgctl()
命令格式
intmsgctl(intmsgid,intcmd,structmsgid_ds*buf);
功能
查询一个消息队列的状态;设置或修改它的状态;撤消一个消息队列
返回值
函数调用成功返回0;不成功返回-1.
参数说明
msgid
该消息队列的描述符;
cmd
规定命令的类型
●IPC_STAT查询消息队列状态,将与msgid相关联的消息队列首标读入buf;
●IPC_SET设置或修改消息队列状态,设置有效用户、组标识、操作允许权,及字节数;
●IPC_RMID撤消描述符为msgid的消息队列;
buf
含有控制参数或查询结果的用户缓冲区的地址,可设置为0
头文件
#include
#include
注意:
设置和撤消消息队列的进程需要有一定的权限,如超级用户、具有有效用户ID、符合msg_perm权限设置等。
四、共享内存通信的系统调用
1、创建或获取一个共享内存
创建/获取一个共享内存的系统调用:
shmget()
命令格式
shmget(key,size,flag);
功能
获得一个内部标识为shmid的共享存储区
说明
该函数创建的共享内存区域并没有立即分配物理内存,而是创建一个文件对象shm_file来描述该区域。
Shm_file文件并不属于磁盘文件,而是由内存页面组成,因此当系统亲面时,其中的内容也随之消失。
语句格式
intshmid=intshmget(key_tkey,intsize,intflag);
参数说明
key
共享存储区关键字,可以由用户指定,如果使用IPC_PRIVATE,则其值由系统产生。
size
存储区的大小(字节数)。
如果存储区定义为字符型,则大小为定义的字符个数;如果存储区定义为整型,大小可以使用sizeof(int)加以定义。
flag
用户设置的标志或访问方式,与消息缓冲shmget中的含义相同。
可以使用066|IPC_CREAT,表示任意进程可读可写。
返回值
正确时返回共享存储区的内部标识符shmid,错误时返回-1。
头文件
#include
#include
2、将共享内存附接到进程的虚拟地址空间
将共享内存附接到进程虚拟地址空间的系统调用:
shmat()
命令格式
字符型共享内存
shmat(intshmid,char*shmaddr,intmsgflg,ulong*raddr);
数值型共享内存
shmat(intshmid,int*shmaddr,intmsgflg,ulong*raddr);
功能
逻辑上将内部标识符为shmid的共享存储区附接到进程的虚拟地址空间shmaddr
语句格式
字符型共享内存
viraddr=(char*)shmat(shmid,shmaddr,shmflag);
数值型共享内存
viraddr=(int*)shmat(shmid,shmaddr,shmflag);
参数说明
shmid
共享存储区的描述符,可以由shmget()的返回值得到。
shmaddr
用户提供的共享存储区附接的虚地址。
若shmaddr为0,则由系统选择一个适当的地址来附接该存储区。
shmflag
规定了对该存储区的操作权限,以及系统是否要对用户规定的地址执行舍去操作。
如果shmflag中设置了SHM_RND,则表示操作系统在必要时舍去这个地址;如果设置SHM_RDONLY则表示只允许读,shmflag为0表示可读可写。
viraddr
附接的虚地址。
若定义为char*viraddr,则该共享内存作为字符存储区使用;若定义为int*viraddr,则该共享内存作为整型存储区使用。
返回值
正确时返回共享存储区附接后的虚地址,错误时返回-1。
头文件
#include