操作系统实验报告
实验题目:进程控制
专业计算机科学与技术
学生姓名
班级学号 12006715 指导教师
指导单位计算机学院
日期 2014年11月13日
一、实验目的
1.学习和了解进程控制的基本和常用的系统调用
fork wait sleep exit exec等等
2. 查看 /usr/src/include/sched.h中的task_struct 数据结构,并分析Linux 操作系统进程状态。
3.通过进程创建的应用实例,深刻理解进程创建的过程
将以下例题输入运行,并分析运行结果
程序例题1
#include
#include
#include
int main(void)
{
pid_t pid;
int data=5;
if((pid=fork())<0)
{
printf("fork error\n");
exit(0);
}
else if(pid==0)
{
data--;
printf("child\'s data is:%d\n",data);
exit(0);
}
else
{
printf("parent\'s data is:%d\n",data);
}
exit(0);
}
程序例题2
用fork创建一个子进程,由其调用execve启动shell命令ps查看系统当前的进程信息#include
#include
#include
main( )
{
pid_t pid;
char *path="/bin/ps";
char *argv[5]={ "ps","-a","-x",NULL};
printf(“Run ps with execve by child process:\n”);
if((pid=fork( ))<0)
{
printf(“fork error!”);
exit(0);
}
else if (pid==0)
{
if(execve(path,argv,0)<0)
{
printf(“fork error!”);
exit(0);
}
printf(“child is ok!\n”);
exit(0);
}
wait( );
printf(“it is ok!\n”);
exit(0);
}
3.创建一个共享内存,实现一个生产者进程写共享内存,一个消费者进程读共享内存,并在写前读后输出写和读的内容。
4.创建一个共享文件,实现一个写者进程写文件,2个读者在写者写后分别读出文件的内容,并给出读后评价。
二、实验指导
Linux中与进程控制相关的几个主要系统调用
三、实验步骤(附程序原码)
实验一:创建文件wang.c,编写C语言程序,实现在程序运行时通过系统调用fork
()创建两个子进程,使父,子三进程并发进行,父亲进程执行时屏幕显示“parent”,儿子进程执行时屏幕显示“son”,女儿进程执行时屏幕显示“daugher”。程序如下:
(进程一)#include
int main()
{ int p1,p2,i;
while((p1=fork())==-1);
if(p1==0)
for(i=0;i<4;i++)
printf("daughter%d\n",i);
else
{ while((p2=fork())==-1);
if(p2==0)
for(i=0;i<4;i++)
printf("son%d\n",i);
else
for(i=0;i<4;i++)
printf("parent%d\n",i);
}
}
(进程二)
#include
int main()
{
int pid;
pid=fork();
switch(pid)
{ case -1:printf("fork fail\n");exit(1);
case 0:printf("subprocess\n");exit(0);
default:wait(0);printf("completed\n");exit(0);
}
}
实验二:
编写程序,用fork创建两个子进程,再用系统调用signal让父进程捕捉键盘上传来的中
断信号,捕捉到中断信号后,父进程用系统调用kill向两个子进程发出信号,子进程终止。父进程等待两个子进程终止后终止。程序代码如下
#include
#include
#include
void waiting(),stop();
int wait_mark;
int main()
{
int p1,p2,stdout;
signal(SIGINT,stop);
while((p1=fork())==-1);
if(p1>0)
{
while((p2=fork())==-1);
if(p2>0)
{
wait_mark=1;
sleep(5);
waiting();
kill(p1,16);
kill(p2,17);
wait(0);
wait(0);
printf("Parent process is killed!\n");
exit(0);
}
else
{
wait_mark=1;
signal(17,stop);
waiting();
lockf(stdout,1,0);
printf("Child process 2 is killed by parent!\n");
lockf(stdout,0,0);
exit(0);
}
}
else
{
wait_mark=1;
signal(16,stop);
waiting();
lockf(stdout,1,0);
printf("Child process 1 is killed by parent!\n");
lockf(stdout,0,0);
exit(0);
}
}
void waiting()
{ while(wait_mark!=0); }
void stop()
{ wait_mark=0; }
四、运行结果及其结果分析
实验一:
结果分析:0:在子进程中,pid变量保存的fork()返回值为0,表示当前进程是
子进程。
>0:在父进程中,pid变量保存的fork()返回值为子进程的pid值。
-1:创建失败。
实验二:
结果分析:从键盘输入中断信号,父进程收到中断信号用系统调用kill向两个子
进程发出信号,子进程收到信号后分别输出Child process 1 is killed by parent!,Child process 2 is killed by parent!结束进程并exit(0),父进程收到两个exit(0)后输出Parent process is killed!结束进程。
五、思考题
1、当首次调用新创建进程时,其入口在哪里?
解:调用fork函数的下一条语句开始。
2、可执行文件加载时进行了哪些处理?
解:可执行文件加载时首先是创建一个新进程的fork系统调用,然后用于实现进程自我终止的exit系统调用;改变进程原有代码的exec系统调用;用于将调用进程挂起并等待子进程终止的wait系统调用;获得进程标识符的getpid系统调用等处理过程。
3、什么是进程同步?wait( )是如何实现进程同步的?
解:异步环境下的一组并发进程因直接制约而互相发送消息而进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。
解:首先程序在调用fork()机那里了一个子进程后,马上调用wait(),使父进程在子进程调用之前一直处于睡眠状态,这样就使子进程先运行,子进程运行exec()装入命令后,然后调用wait(0),使子进程和父进程并发执行,实现进程同步。