当前位置:首页 > 计算机组成原理与操作系统-实验指导书
《操作系统原理及应用》实验指导书
系统调用exec和fork( )联合使用能为程序开发提供有力支持。用fork( )建立子进程,然后在子进程中使用exec( ),这样就实现了父进程与一个与它完全不同子进程的并发执行。
一般,wait、exec联合使用的模型为: int status; ............
if (fork( )= =0) {
...........; execl(...); ...........; }
wait(&status); 3、wait( )
等待子进程运行结束。如果子进程没有完成,父进程一直等待。wait( )将调用进程挂起,直至其子进程因暂停或终止而发来软中断信号为止。如果在wait( )前已有子进程暂停或终止,则调用进程做适当处理后便返回。wait( )给我们提供了一种实现进程同步的简单方法。
系统调用格式: int wait(status) int *status;
其中,status是用户空间的地址。它的低8位反应子进程状态,为0表示子进程正常结束,非0则表示出现了各种各样的问题;高8位则带回了exit( )的返回值。exit( )返回值由系统给出。
核心对wait( )作以下处理:
(1)首先查找调用进程是否有子进程,若无,则返回出错码;
(2)若找到一处于“僵死状态”的子进程,则将子进程的执行时间加到父进程的执行时间上,并释放子进程的进程表项;
(3)若未找到处于“僵死状态”的子进程,则调用进程便在可被中断的优先级上睡眠,等待其子进程发来软中断信号时被唤醒。
4、sleep( ) 睡眠指定时间。 系统调用格式:
void sleep(int second)
其中,second为指定睡眠的秒数。该函数使得当前进程自我阻塞second秒,由执行态转换成阻塞态,直到系统唤醒。
5、exit( )
终止进程的执行。 系统调用格式:
void exit(status) int status;
其中,status是返回给父进程的一个整数,以备查考。 为了及时回收进程所占用的资源并减少父进程的干预,LINUX/LINUX利用exit( )来实现进程的自我终止,通常父进程在创建子进程时,应在进程的末尾安排一条exit( ),使子进程自我终止。exit(0)表示进程正常终止,exit(1)表示进程运行有错,异常终止。
如果调用进程在执行exit( )时,其父进程正在等待它的终止,则父进程可立即得到其返回的整数。核心须为exit( )完成以下操作:
(1)关闭软中断 (2)回收资源 (3)写记帐信息
(4)置进程为“僵死状态”
实验指导
1、参照参考程序编写程序,其中父进程无限循环。在后台执行该程序。
12
《操作系统原理及应用》实验指导书
[root@localhost lab2]# vi fork_1.c
[root@localhost lab2]# gcc fork_1.c -o def [root@localhost lab2]# ./def & [1] 3620
def fork_1.c
子进程用exec( )装入命令ls ,exec( )后,子进程的代码被ls的代码取代,这时子进程的PC指向ls的第1条语句,开始执行ls的命令代码。
如果是下面这种:
[root@localhost lab2]# ./def
则只有用^c强行终止父进程,则在第2步结果就不同了,父子进程都成为僵死进程。 2、显示当前终端上启动的所有进程。 [root@localhost lab2]# ps -af
UID PID PPID C STIME TTY TIME CMD root 3620 3126 0 20:11 pts/1 00:00:00 ./def
root 3621 3620 0 20:11 pts/1 00:00:00 [ls
其中,‖
3、用kill命令直接杀死该子进程,看看是否能够成功? [root@localhost lab2]# kill -9 3621 [root@localhost lab2]# ps -af
为什么不能杀死?因为父进程还没结束。
4、用kill命令杀死父进程之后呢?解释原因。 [root@localhost lab2]# kill -9 3620 [root@localhost lab2]# ps -af
但是如果父子进程都异常终止,则由Init进程回收所有僵死进程资源。 5、修改程序fork_1.c,在父进程执行‖ while(1)‖之前,添加代码‖wait(0);‖。在后台执行该程序。显示当前终端上启动的所有进程。解释原因。
6、修改以上程序,在子进程执行‖ printf(“Is son:\\n”);‖之前添加代码 ―sleep(1);‖。观察多进程的执行序列,解释原因。
7、选作:修改“多进程环境实验”中的参考程序,在“子进程1段”前添加代码“sleep(2);”,在“父进程段b”前添加代码“wait(0); wait(0);”。观察多进程的执行序列,解释原因。试一下作其它修改后的效果?
参考程序
#include
int pid;
pid=fork( ); /*创建子进程*/
switch(pid)
{
case -1: /*创建失败*/ printf(\ exit(1);
case 0: /*子进程*/
13
《操作系统原理及应用》实验指导书
printf(“Is son:\\n”);
execl(\
printf(\ exit(1);
default: /*父进程*/ printf(\ while(1) sleep(1); exit(0); }
}
思考题
(1)可执行文件加载时进行了哪些处理?参考程序中,什么时候执行语句fail!\\n\‖ ?
(2)实验指导中的第5步,wait( )是如何实现进程同步的? (3)实验指导中的第6步,sleep(1)为什么能导致进程切换?
14
‖printf(\ 《操作系统原理及应用》实验指导书
实验四 设备管理实验
实验目的
1、理解设备管理的无关性,了解linux中的设备管理方法 2、了解并能使用linux提供的设备管理接口
实验内容
1、利用linux提供的命令接口,查看系统中当前设备的情况。学习和掌握对设备文件的管理方法。 2、编写用户程序,利用设备管理的无关性,以文件方式访问设备,与设备交互。学习对设备管理的编程技巧。
实验基础
一、Linux操作系统中的设备管理
在Linux操作系统下有三类设备文件类型,字符设备(char divce)、块设备(block device)和网络设备(network device)。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。
传统方式中的设备管理中,除了设备类型外,内核还需要一对称作主次设备号的参数,才能唯一标识一个设备。主设备号相同的设备使用相同的驱动程序,次设备号用于区分具体设备的实例。比如PC 机中的IDE 设备,一般主设备号使用3,WINDOWS 下进行的分区,一般将主分区的次设备号为1,扩展分区的次设备号为2、3、4,逻辑分区使用5、6….。
设备类型、主次设备号是内核与设备驱动程序通信时所使用的,但是对于开发应用程序的用户来说比较难于理解和记忆,所以Linux 使用了设备文件的概念来统一对设备的访问接口,在引入设备文件系统(devfs)之前Linux 将设备文件放在/dev 目录下,设备的命名一般为设备文件名+数字或字母表示的子类,例如/dev/hda1、/dev/hda2 等。在Linux-2.4 内核中引入了设备文件系统(devfs),所有的设备文件作为一个可以挂装的文件系统,这样就可以被文件系统进行统一管理,从而设备文件就可以挂装到任何需要的地方。
因此每个设备有一个文件名,在文件系统中占一个inode,由于设备驱动的支持,正规文件的调用open、close、read、write对一个设备文件来说有相应的含义。 二、/proc特殊文件系统
/proc是一特殊文件系统。其目录下显示了系统运行时的各种动态信息。其中与设备管理有关的文件:
1、/proc/devices文件:列出了主要的字符设备和块设备编号以及分配这些编号的驱动程序的名字。 2、/proc/ioports文件:列出了对各种设备驱动程序如磁盘、以太网卡、声卡等所注册的I/O端口范围。
3、/proc/dma文件:列出了被驱动程序留作专用的DMA通道以及驱动程序赋予的名字。 4、/proc/scsi目录:该目录下有一个文件/proc/scsi/scsi和多个子目录/proc/scsi/$driver,文件/proc/scsi/scsi中记录了所有被检测到的SCSI设备,每个$driver子目录对应一个控制器驱动程序,子目录下的每一个文件/proc/scsi/$driver/$n对应与安装的控制器的一个单独实例。
5、/proc/rtc文件:记录了硬件实时时钟的相关信息,包括当前日期、时间、闹钟设置、电池状态
15
共分享92篇相关文档