实验内容:进程管理
一、实验目的
1、 掌握Linux中进程的创建方法及执行情况; 2、 加深对进程、进程树等概念的理解;
3、掌握Linux中如何加载子进程自己的程序;
4、掌握父进程通过创建子进程完成某项任务的方法; 5.、掌握系统调用exit()和_exit()调用的使用。
6、分析进程竞争资源的现象,学习解决进程互斥的方法;进一步认识并发执行的实质 二、实验内容
(一)进程的创建
1、编写一段程序,使用系统调用fork( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符。 #include
int p,x; p=fork(); if(p>0) { x=fork(); if(x>0) printf(\ else printf(\ } else printf(\
}
输出结果: child1 child2 father
2、运行以下程序,分析程序执行过程中产生的进程情况。
#include
int p,x; p=fork(); if (p>0)
fork(); else{
fork();
fork(); }
sleep(15); }
实验步骤:
编译连接 gcc –o forktree forktree.c 后台运行 ./forktree &
使用 pstree –h 查看进程树 运行结果:
├─gnome-terminal─┬─bash─┬─forktree─┬─forktree─┬─forktree───forktree
│ │ │ │ └─forktree │ │ │ └─forktree │ │ └─pstree 分析:程序运行,系统首先创建一个进程forktree,执行到p=fork()创建一个子进程forktree,子进程获得处理机优先执行,父进程等待;执行else,当执行到第一个fork()函数时,子进程创建了一个进程forktree,称之为孙进程,孙进程获得处理机往下执行,子进程等待;执行到第二个fork()函数时,孙进程又创建一个进程forktree,称之为重孙进程,重孙进程很快执行完,将处理机还给孙进程,孙进程很快执行完,将处理机还给子进程;子进程继续往下执行,执行到第二个fork()函数,又创建一个进程forktree,称之为第二孙进程,并获得处理机执行,此进程很快执行完,将处理机还给子进程,子进程也很快执行完,将处理机还给父进程,父进程P>0执行if语句,运行fork()函数,又创建一个进程forktree,称之为第二子进程,此进程获得处理机执行很快运行完,将处理机还给父进程,父进程运行sleep(15)语句,休眠15秒,用pstree命令查询进程树。
3、运行程序,分析运行结果。 #include
int p,x,ppid,pid; x=0; p=fork(); if(p>0)
{ printf(\ ppid=getpid();
printf(\ } else
{ printf(\ pid=getpid();
printf(\
} }
运行结果:
Parent output x=1
This id number of parent is:ppid=3110 Child output x =1
This is number of child is:pid=3111
分析:fork创建进程的时候子进程与父进程共享代码区,子进程复制父进程的数据区,所以,两个进程中的数据互不影响都是1。
4、loop.c
#include
while(1){ }; {
实验步骤:
编译 gcc loop.c –o loop
后台运行 ./loop &(可多次使用该命令) 多次使用ps命令查看进程状态 结果:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 S 1000 2645 2643 0 80 0 - 1444 wait pts/0 00:00:00 bash 0 R 1000 3622 2645 78 80 0 - 403 - pts/0 00:00:18 loop 0 R 1000 3627 2645 39 80 0 - 403 - pts/0 00:00:02 loop 0 R 1000 3628 2645 39 80 0 - 403 - pts/0 00:00:01 loop 0 R 1000 3630 2645 0 80 0 - 625 - pts/0 00:00:00 ps
(二)进程控制
1、设计一程序,父进程创建一子进程,子进程的功能是输出“hello world!”,使用execl()加载子进程的程序。
程序代码如下: execl.c程序: #include
{ printf(\ execl(\ printf(\ } }
hello.c程序: #include
printf(\}
输出结果: child is running! hello world!
father is running!
2、运行以下程序,分析程序执行结果。 #include
printf(\ else{
printf(\n”); printf(\”); _exit(0); } }
执行结果: this is child first
this is parent[chun@RedFlagLinux jjz]$ 换为exit(0)的执行结果: this is child first
this is child second this is parent[chun@RedFlagLinux jjz]$
分析:_exit()只是返回进程状态SZOMB,不清除缓冲区内容; exit(0)表示进程正常终止;
(三)、进程的互斥
1、利用cat to_be_locked.txt 查看下面程序的输出结果。 #include
#include
执行结果:daughter0 daughter1 daughter2
fp=fopen(\if(fp==NULL) { printf(\ exit(-1); } while((p1=fork())==-1); /*创建子进程p1*/ if(p1==0) { lockf(*fp,1,0); /*加锁*/ for(i=0;i<10;i++) fprintf(fp,\ lockf(*fp,0,0); /*解锁*/ } else { while((p2=fork())==-1); /*创建子进程p2*/ if(p2==0) { lockf(*fp,1,0); /*加锁*/ for(i=0;i<10;i++) fprintf(fp,\ lockf(*fp,0,0); /*解锁*/ } else { wait(NULL); lockf(*fp,1,0); /*加锁*/ for(i=0;i<10;i++) fprintf(fp,\ lockf(*fp,0,0); /*解锁*/ } } fclose(fp);