实验三 进程管理及进程通信
实验环境:
Linux操作系统
实验目的:
(1)利用Linux提供的系统调用设计程序,加深对进程概念的理解。
(2)体会系统进程调度的方法和效果。
(3)了解进程之间的通信方式以及各种通信方式的使用。
实验方法:
用vi 编写c 程序(假定程序文件名为prog1.c) 编译程序
$ gcc -o prog1.o prog1.c
或 $ cc -o prog1.o prog1.c
运行
$./prog1.o
实验内容及步骤:
实验1
编写程序。显示进程的有关标识(进程标识、组标识、用户标识等)。经过5 秒钟后,执行另一个程序,最后按用户指示(如:Y/N)结束操作。
编程截图:
运行结果:
实验2
参考例程1,编写程序。实现父进程创建一个子进程。体会子进程与父进程分别获得不同返回值,进而执行不同的程序段的方法。
例程1:利用fork()创建子进程
/* 用fork()系统调用创建子进程的进程通信方式例子*/
main()
{
int i;
if (fork()) /*父进程执行的程序段*/
i=wait(); /* 等待子进程结束*/{
printf("It is parent process.\n");
printf("The child process,ID number %d, is finished.\n",i);
}
else{
Printf(“It is child process.\n”);
Sleep(10);
Exit();
}
}
运行结果:
思考:
子进程是如何产生的? 又是如何结束的?子进程被创建后它的运行环境是怎 样建立的?
答:是由父进程用fock()函数创建形成的,通过exit()函数自我结束,子进程被创建后核心
将其分配一个进程表项和进程标识符,检查同时运行的进程数目,并且拷贝进程表项的数据,由子进程继承父进程所有文件。
实验3
参考例程2,编写程序。父进程通过循环语句创建若干子进程。探讨进程的家族树以 及子进程继承父进程的资源的关系。
例程2:循环调用fork()创建多个子进程。
/*建立进程树*/
#include<unistd.h>
main()
{ int i;
printf(“My pid is %d, my father’s pid is %d\n”,getpid()
,getppid());
for(i=0; i<3; i++)
if(fork()==0)
printf(“%d pid=%d ppid=%d\n”, i,getpid(),getppid());
else
{ j=wait(0);
Printf(“ %d:The chile %d is finished.\n” ,getpid(),j);
}
}
运行结果:
思考:
① 画出进程的家族树。
答:进程家族树
实验4
参考例程3 编程,使用fork( )和exec( )等系统调用创建三个子进程。子进程分别启动
不同程序,并结束。反复执行该程序,观察运行结果,结束的先后,看是否有不同次 序。
例程3:创建子进程并用execlp()系统调用执行程序的实验
/*创建子进程,子进程启动其它程序*/
#include<stdio.h>
#include<unistd.h>
main()
{
int child_pid1,child_pid2,child_pid3;
int pid,status;
setbuf(stdout,NULL);
child_pid1=fork(); /*创建子进程1*/
if(child_pid1==0)
{ execlp("echo","echo","child process 1",(char *)0); /*子进程1 启动其它程序*/
perror("exec1 error.\n ");
exit(1);
}
child_pid2=fork(); /*创建子进程2*/
if(child_pid2==0)
{ execlp("date","date",(char *)0); /*子进程2 启动其它程序*/
perror("exec2 error.\n ");
exit(2);
}
child_pid3=fork(); /*创建子进程3*/
if(child_pid3==0)
{ execlp("ls","ls",(char *)0); /*子进程3 启动其它程序*/
perror("exec3 error.\n ");
exit(3);
}
puts("Parent process is waiting for chile process return!");
while((pid=wait(&status))!=-1) /*等待子进程结束*/
{ if(child_pid1==pid) /*若子进程1 结束*/
printf("child process 1 terminated with status %d\n",(status>>8));
else
{if(child_pid2==pid) /*若子进程2 结束*/
printf("child process 2 terminated with status %d\n",(status>>8));
else
{ if(child_pid3==pid) /*若子进程3 结束*/
printf("child process 3 terminated with status %d\n" ,(status>>8));
}
}
}
puts("All child processes terminated."); puts("Parent process terminated."); exit(0);
}
运行结果:
思考:
子进程运行其它程序后,进程运行环境怎样变化的?反复运行此程序看会有
什么情况?解释一下。
答:子进程运行其他程序后,这个进程就完全被新程序替代。由于并没有产生新进程,所以进程标识号不变,除此之外的旧进程的其他信息,代码段,数据段,栈段等均被新程序的信息所替代。新程序从自己的main()函数开始进行。反复运行此程序发现结束的先后次序是不可预知的,每次运行的结果不一样。原因是当每个子进程运行其他程序是,他们的结束随着其他程序的结束而结束,所以结束的先后次序在变化。
实验5
参考例程4 编程,验证子进程继承父进程的程序、数据等资源。如用父、子进程修改 公共变量和私有变量的处理结果;父、子进程的程序区和数据区的位置。
例程4:观察父、子进程对变量处理的影响
/*创建子进程的实验。子进程继承父进程的资源,修改了公共变量globa 和私有变 量vari。观察变化情况。*/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int globa=4;
int main()
{
pid_t pid; int vari=5; printf("before fork.\n");
if ((pid=fork())<0)/*创建失败处理*/
{
printf("fork error.\n");
exit(0);
}
else if(pid==0)
{ /*子进程执行*/
globa++;
vari--;
printf("Child %d changed the vari and globa.\n",getpid());
}
else /*父进程执行*/
printf("Parent %d did not changed the vari and globa.\n",getpid());
printf("pid=%d, globa=%d, vari=%d\n",getpid(),globa,vari); /*都执行*/
exit(0);
}
运行结果:
思考:
子进程被创建后,对父进程的运行环境有影响吗?解释一下
答:父进程被创建后,对父进程的运行环境无影响,因为当子进程在运行时,他有自己的代码段和数据段,这些都可以做修改。但是父进程的代码和数据段是不会随着子进程数据段和代码段的改变而改变。
实验6
参照《实验指导》第五部分中“管道操作的系统调用”。复习管道通信概念,参考例 程5,编写一个程序。父进程创建两个子进程,父子进程之间利用管道进行通信。要 求能显示父进程、子进程各自的信息,体现通信效果。
例程5:管道通信的实验
/*程序建立一个管道fd*/
/*父进程创建两个子进程P1、P2 */
/*子进程P1、P2 分别向管道写入信息*/
/*父进程等待子进程结束,并读出管道中的信息*/
#include<stdio.h>
main()
{
int i,r,j,k,l,p1,p2,fd[2];
char buf[50],s[50];
pipe(fd); /*建立一个管道fd*/
while((p1=fork())==-1); /*创建子进程1*/
if(p1==0)
lockf(fd[1],1,0); /*子进程1 执行*/
/*管道写入端加锁*/
{
sprintf(buf,"Child process P1 is sending messages! \n");
printf("Child process P1! \n");
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论