进程的创建与并发执行 带答案版
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验二进程管理
2.1 进程的创建与并发执行
1. 实验目的
(1) 加深对进程概念的理解, 理解进程和程序的区别。
(2) 认识并发进程的实质。分析进程争用资源的现象,学习解决进程互斥的方法。
(3) 理解系统调用和用户命令的区别。
2. 实验类型:验证型
3. 实验学时:2
4. 实验原理和知识点
(1) 实验原理:程序的并发执行具有随机性和不可再现性。程序并发执行会导致资源共享和资源竞争,各程序向前执行的速度会受资源共享的制约。程序的动态执行过程用进程这个概念来描述。由于向前推进的速度不可预知,所以多个进程并发地重复执行,整体上得到的结果可能不同。但要注意,就其中某单个进程而言,其多次运行结果是确定的。
(2) 知识点:进程、子进程、并发执行的特性;
5. 实验环境(硬件环境、软件环境) :
(1) 硬件环境:Intel Pentium III 以上CPU,128MB 以上内存,2GB 以上硬盘
(2) 软件环境:linux 操作系统。
6. 预备知识
(1) fork() 系统调用
头文件:#include
/* 是POSIX 标准定义的unix 类系统定义符号常量的头文件,包含了许多UNIX 系统服务的函数原型,例如read 函数、write 函数和getpid 函数*/ 函数原型:pid_t fork(void);
/* 是Linux 下的进程号类型,也就是Process ID _ Type 的缩写。其实是宏定义的unsigned int 类型*/
函数功能:fork 的功能是创建子进程。调用fork 的进程称为父进程。如图 2.1 所示。子进程是父进程的一个拷贝,它继承了父进程的用户代码、组代码、环境变量、已打开的文件代码、工作目录及资源限制。fork 语句执行后,内核向父进程返回子进程的进程号,向子进程返回0。父子进程都从fork() 的下一句开始并发执行。
返回值:
返回值==-1 :创建失败。
返回值==0 :程序在子进程中。
返回值>0 :程序在父进程中。 (该返回值是子进程的进程号)
编程提示:虽然子进程是父进程的一个复制品,但父子的行为是不同的。编程时要抓住内核的返回值。通过返回值,可以知道是父进程还是子进程,因而可以编写不同行为的代码。
⑵wait()
系统调用
头文件:#in clude
函数参数:status 是子进程退出时的状态信息。 返回值:成功则返回子进程号,否则返回
-1。
⑶getpid()
系统调用
头文件:unistd.h ,在 VC++6.0 下可以用 process.h 函数原型:pid_t getpid(void);
函数功能:wait 的功能是将父进程挂起,等待子进程终止。 getpid 函数用来取得目前进程
的进程ID ,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题。 返回值:目前进程的进程
ID 。
(4) 其他系统调用 exit -终止进程
执行一个应用程序 改变进程的优先 7. 实验内容与步骤(将所有截图换成用户名为你们自己姓名的拼音,并回答所有的问题)
(1 )运行图2.1所示程序
将图2.1中的源程序保存为 e201.c 在终端中编译gcc p e201 e201.c
运行./e201
[y i n ji.aottYou Yo u ' ]S gcc -o e20i e201 . c
I yi njiYouYou * )3 ./e201
son
father
父退程(进程号;1869)
^include
pl~fark (); -------------------------- t —这里裱返回1听口 if (pi==a ){
printf (H Bon\n n ); while (1); }else {
printf (rt father\n H ): wait ();
仓健进程
子进程(进程号:16TO)
注;
子进程是父送程的一个拷贝
父子送程都从下一包幵绘执行. 父子送程年发技厅°
#mcl^de
t_这里披返回D
if {pl==O}<
printf(^sonXn"}; while(1); }else {
printf(n father\n n }; wait (};
图 2.1 fork()
创建进程示意图
发出wait 调用的进程只要有子进程,就会睡眠 exec nice
此时,程序为死循环,在该终端中无法继续输入命令执行,于是,我们可以暂时不管这一个终端,而是再新建一个终端,然后键入PS -3,列出当前所有进程
[yi nJiaotYou Y QU ']S ps -c
FID TTY TIME:CMD
1 ?00s00:00ini t
2 ?00:00:00oisratian/O
3 ?00:00:00ksoftirqd/0
4 ?00100:00*atchdlog/0
5 ?00:00:00events/O
6 ?00:00:00khelper
7 ?OOsOOiOO kLhread
]0 ?00:00:00kblockd/O
11 ?00:00:00kacpid
175 ?DOiCiO:cqueue/D
观察屏幕,是否有两个名为e201的进程。比较它们的进程号,判别哪个是父进程,哪个是子进程。
3713 pts/1 bash
3755 pts/I 00:00:00 c201
3756 pts/1 00i00:23 e2dl
3762 pts/2 00;00;00 bash
3790 pts/2 00:00:00 ps
[y i nj iou "]S
[yinjiaotyouVou ']S kill 3755
[y i njl tntYauYou " |S kill 3756 [ylnJiao»YouYou "]3 ps -e
FID TTV TIME CMD
1 ? 00:00:00 init
2 ? OO; 00: 00 mi g rail DI)/0
3 ? 00:00:00 ksoftirqd/0
程序中的while(1); 语句是为了不让程序退出来,以便于你观察进程状态。用kill 命令把这两个进程终止。可见,第一个终端如下图所示,已经从死循环中解救出来了。
[yinjiaotYouYou - Z&201
son
father
已终止
[y i n j i. noiiYouYd u *jS |
当然,最简单粗暴的方法不是关闭相关进程,而是直接通过对图
2.1的程序稍加改进,可看见两个进程的进程号。
#include
int main()
{
int pl:
pl=fork();
if(pi=e)
{
p rlntf (' son : ^dXn * (getpid (});
//whiled);
}
else
{
wait();
p rintf (" fathe r:%d\n", getpid()); }
ctrl+c 强制结束。