1 .实验目的 通过进程的创建、撤消和运行加深对进程概念和进程并发执行的理解,明确进程与程序之间的区别。 【答:进程概念和程序概念最大的不同之处在于: (1)进程是动态的,而程序是静态的。 (2)进程有一定的生命期,而程序是指令的集合,本身无“运动”的含义。没有建立进程的程序不能作为1个独立单位得到操作系统的认可。 (3)1个程序可以对应多个进程,但1个进程只能对应1个程序。进程和程序的关系犹如演出和剧本的关系。 (4)进程和程序的组成不同。从静态角度看,进程由程序、数据和进程控制块(PCB)三部分组成。而程序是一组有序的指令集合。】
2 .实验内容 (1) 了解系统调用fork()、execvp()和wait()的功能和实现过程。 (2) 编写一段程序,使用系统调用fork()来创建两个子进程,并由父进程重复显示字符串“parent:”和自己的标识数,而子进程则重复显示字符串“child:”和自己的标识数。 (3) 编写一段程序,使用系统调用fork()来创建一个子进程。子进程通过系统调用execvp()更换自己的执行代码,新的代码显示“new program.”。而父进程则调用wait()等待子进程结束,并在子进程结束后显示子进程的标识符,然后正常结束。
3 .实验步骤 (1)gedit创建进程1.c (2)使用gcc 1.c -o 1编译并./1运行程序1.c #include #include #include #include void mian(){ int id; if(fork()==0) {printf(“child id is %d\n”,getpid()); } else if(fork()==0) {printf(“child2 id %d\n”,getpid()); } else {id=wait(); printf(“parent id is %d\n”,getpid()); } }
(3)运行并查看结果 child’s pid=2894 child’s pid=2994 parent’s pid=2849 child’s pid=2897 child’s pid=2897 parent’s pid=2849 child’s pid=2894 child’s pid=2994 parent’s pid=2849
(4)gedit创建进程2.c 使用gcc 2.c -o 2编译并./2运行程序2.c#include #include #include #include #include int main() { pid_t pid; char *a[]={“ls”,"-l","/etc/passwd",0}; int result; pid=fork(); if(pid printf(“new program !\n”); execvp(“ls”,a); exit(0); } else{ int e=waitpid(pid,&result,0); printf(“child peocess PID:%d\n”,e); exit(0); } } (5)
(6)运行并查看结果 new program ! -rw-r–r--. 1 root root 2456 Apr 14 2019 /etc/passwd child peocess PID:29035
4 .思考 (1) 系统调用fork()是如何创建进程的? 【答:(1)申请空白PCB (2)为新进程分配资源 (3)初始化进程控制块 (初始化标识信息,初始化处理机状态信息,初始化处理机控制信息,) (4)将新进程插入就绪队列】 (2)当首次将CPU 调度给子进程时,其入口在哪里? 【答:进程的进程控制块(PCB)结构中有指向其TTS(任务状态段)的指针, TTS里面存放着进程的入口。】 (3)系统调用execvp()是如何更换进程的可执行代码的? 【答:一个库函数通过调用execve来调用内核服务来执行指明的程序】 (4) 对一个应用,如果用多个进程的并发执行来实现,与单个进程来实现有什么不同? 【答:相对于单个进程而言,程序并发执行就是系统中的各个部分不再以单纯串行方式工作,在同一时刻系统中不是只有一个活动,而是存在许多并行活动。并且充分利用多核CPU的计算能力,方便进行业务拆分,提升应用性能。其次,时间片是CPU分配给各个线程的时间,因为时间非常短,所以CPU不断通过切换线程,让我们觉得线程是同时执行的,时间片一般是几十毫秒.而每次切换时,需要将当前的状态保存起来,以便能够进行恢复先前的状态,而这个切换是非常消耗性能的,过于频繁的切换反而无法发挥出多线程编程的优势.最后,因为单进程不会和其它进程争用竟源,也不会和其它进程有什么执行顺序不合理导理死锁,多进程并不仅发失去其封闭性并且会导致死锁现象】