1、实验目的
(1)加深对进程概念的理解,明确进程和程序的区别。
(2)进一步认识并发执行的实质。
(3)分析进程竞争资源现象,学习解决进程互斥的方法。
2、实验预备内容
(1)阅读Linux的sched.h源文件,加深对进程管理概念的理解。
(2)阅读Linux的fork.c源文件,分析进程的创建过程。
3、实验内容
(1)进程的创建
编写一段源程序,使系统调用fork()创建两个子进程,当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。试观察纪录屏幕上的显示结果,并分析原因。
(2)进程的控制
修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕出现的现象,并分析原因。
如果在程序中使用调用lockf()来给每一个子进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。
4、思考
(1)系统是怎样创建进程的?
(2)可执行文件加载时进行了哪些处理?
(3)当首次调用新创建进程时,其入口在哪里?
5、实验过程
5.1进程创建
第一步:
创建fork文件夹,在它下面创建first.c文件
第二步:
编写程序:
第三步:
编译文件,得到a.out
第四步:
运行文件,观察并记录结果
总结:结果为abc
或bac
,因为fork()
创建进程所需要的时间要多于输出一个字符的时间,所以为abc
或bac
。
写了一个for循环再次验证结论
运行:
分析:由于函数printf()
输出的字符串之间不会被中断,因此,字符串内部的字符顺序输出时不变。但是,由于进程并发执行时的调度顺序和父子进程的抢占处理机问题,处处字符串的顺序和先后随着执行的不同而发生变化。(摘自操作系统实验指导书)
5.2 进程控制
修改已经编好的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。
如果在程序中使用系统调用lockf()
来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。
将上文建立的se.c
文件中的代码改为以下代码:
结果:
结果1:
结果2:
分析:当使用lockf
后daughter
的printf
无法被抢占,则先输出daughter
,另外两个的先后取决于进程在处理机中的先后顺序。
思考题
(1)系统是怎样创建进程的?
首先,fork() 函数拷贝当前进程创建子进程。产生的子进程与父进程的区别仅在与 PID 与 PPID 以及某些资源和统计量,例如挂起的信号等。准备好进程运行的地址空间后,exec() 函数族负责读取可执行程序,并将其加载到相应的位置开始执行。(来自百度回答)
(2)可执行文件加载时进行了哪些处理?
将源代码转换为机器可认识代码的过程。编译程序读取源程序(字符流),对之进行词法
和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,
并且按照操作系统对可执行文件格式的要求链接生成可执行程序。具体经过以下几个处理: C源程序一>编译预处理一>编译一>优化程序一>汇编程序一>链接程序一>可执行文件
(3)当首次调用新创建进程时,其入口在哪里?
在进程队列的ready状态下,由离自己最近的父进程执行调度,即入口在最近的父进程处。(来自百度知道)