1、实验二 进程观察实验(二):进程的控制实验目的1、了解进程创建后对进程控制的系统调用,可实现对进程的有效控制2、掌握进程的睡眠、同步、撤消等进程控制方法实验内容1、通过相关命令,对进程的状态进行控制。2、编写程序,使用 fork( )创建一个子进程。使用相关的系统调用控制进程的状态。观察并分析多进程的执行次序及状态转换。实验基础一、进程的控制进程因创建而存在,因执行完成或异常原因而终止.在进程的生命周期中,进程在内存中有三种基本状态:就绪,执行,阻塞 .进程状态的转换是通过进程控制原语来实现的。Linux 操作系统提供了相应功能的系统调用及命令,来实现用户层的进程控制。二、相关的命令(1)睡眠
2、指定时间执行格式:# sleep xx 为指定睡眠的秒数。(2)结束或终止进程 kill执行格式:# kill -9 PID (PID 为利用 ps 命令所查出的 process ID)例: kill -9 456 终止 process ID 为 456 的 process(3)后台(background)执行 process command 的命令执行格式:# command char *path,*arg0,*arg1,.,*argn;另一种是给出指向参数表的指针,如:int execv(path,argv);char *path,*argv ;另外,在 linux 中,出于安全的考虑,限
3、制了 exec()可以执行的新程序的位置为系统指定的搜索路径。例如:execl(“/bin/ls”,”ls”,NULL);execl(“/usr/bin/gcc”,”-v”,NULL);execl(“./test”,NULL); /当前目录下的可执行程序2、exec( ) 和 fork( )联合使用系统调用 exec 和 fork( )联合使用能为程序开发提供有力支持。用 fork( )建立子进程,然后在子进程中使用 exec( ),这样就实现了父进程与一个与它完全不同子进程的并发执行。一般,wait、exec 联合使用的模型为:int status;if (fork( )= =0) .;ex
4、ecl(.);.;wait(3、wait( )等待子进程运行结束。如果子进程没有完成,父进程一直等待。wait( )将调用进程挂起,直至其子进程因暂停或终止而发来软中断信号为止。如果在 wait( )前已有子进程暂停或终止,则调用进程做适当处理后便返回。wait( )给我们提供了一种实现进程同步的简单方法。系统调用格式:int wait(status) int *status;其中,status 是用户空间的地址。它的低 8 位反应子进程状态,为 0 表示子进程正常结束,非 0 则表示出现了各种各样的问题;高 8 位则带回了 exit( )的返回值。exit( )返回值由系统给出。核心对 wa
5、it( )作以下处理:(1)首先查找调用进程是否有子进程,若无,则返回出错码;(2)若找到一处于“僵死状态”的子进程,则将子进程的执行时间加到父进程的执行时间上,并释放子进程的进程表项;(3)若未找到处于“僵死状态”的子进程,则调用进程便在可被中断的优先级上睡眠,等待其子进程发来软中断信号时被唤醒。4、sleep( )睡眠指定时间。系统调用格式:void sleep(int second)其中,second 为指定睡眠的秒数。该函数使得当前进程自我阻塞 second 秒,由执行态转换成阻塞态,直到系统唤醒。5、exit ( )终止进程的执行。系统调用格式:void exit(status)in
6、t status;其中,status 是返回给父进程的一个整数,以备查考。为了及时回收进程所占用的资源并减少父进程的干预,LINUX/LINUX 利用 exit( )来实现进程的自我终止,通常父进程在创建子进程时,应在进程的末尾安排一条 exit( ),使子进程自我终止。exit(0)表示进程正常终止,exit(1) 表示进程运行有错,异常终止。如果调用进程在执行 exit( )时,其父进程正在等待它的终止,则父进程可立即得到其返回的整数。核心须为 exit( )完成以下操作:(1)关闭软中断(2)回收资源(3)写记帐信息(4)置进程为“僵死状态” 实验指导1、参照参考程序编写程序,其中父进程
7、无限循环。在后台执行该程序。rootlocalhost lab2# vi fork_1.c rootlocalhost lab2# gcc fork_1.c -o defrootlocalhost lab2# ./def ”。在后台执行该程序。显示当前终端上启动的所有进程。解释原因。6、修改以上程序,在子进程执行” printf(“Is son:n”);”之前添加代码 “sleep(1);”。观察多进程的执行序列,解释原因。7、选作:修改“多进程环境实验”中的参考程序,在“子进程 1 段”前添加代码“sleep(2);”,在“父进程段 b”前添加代码“wait(0); wait(0);”。观察
8、多进程的执行序列,解释原因。试一下作其它修改后的效果?参考程序#include#includemain( ) int pid; pid=fork( ); /*创建子进程*/switch(pid) case -1: /*创建失败*/printf(“fork fail!n“);exit(1);case 0: /*子进程*/printf(“Is son:n”); execl(“/bin/ls“,“ls“,“-1“,NULL); printf(“exec fail!n“);exit(1);default: /*父进程*/printf(“ls parent:n“);while(1) sleep(1);e
9、xit(0);思考题(1)可执行文件加载时进行了哪些处理?参考程序中,什么时候执行语句 ”printf(“exec fail!n“);” ?(2)实验指导中的第 5 步,wait( )是如何实现进程同步的? (3)实验指导中的第 6 步,sleep(1)为什么能导致进程切换?创建进程:#include #include #include #include #include #include #include int main()pid_t pid;if(-1 = (pid = fork()printf(“Error happened in fork function!n“);return 0;
10、if(0 = pid)printf(“This is child process: %dn“, getpid();elseprintf(“This is parent process: %dn“, getpid();return 0;使用 wait 函数让父进程等待子进程运行结束后才开始运行。注意,为了证明父进程确实是等待子进程运行结束后才继续运行的,我们使用了 sleep 函数。但是,在 linux 下面,sleep 函数的参数是秒,而 windows 下面 sleep 的函数参数是毫秒。#include #include #include int main(int argc, char* argv)pid_t pid;pid = fork();if(0 = pid)printf(“This is child process, %dn“, getpid();sleep(5);elsewait(NULL);printf(“This is parent process, %dn“, getpid();return 1;