实验一 进程控制实验
班级:学号:姓名:
一、实验目的
加深对于进程并发执行概念的理解。实践并发进程的创建和控制方法。观察和
体验进程的动态特性。进一步理解进程生命期期间创建、变换、撤销状态变换的过
程。掌握进程控制的方法,了解父子进程间的控制和协作关系。练习 Linux 系统中
进程创建与控制有关的系统调用的编程和调试技术。
二、实验内容
参考以上示例程序中建立并发进程的方法,编写一个多进程并发执行程序。父进
程首先创建一个执行ls命令的子进程然后再创建一个执行ps命令的子进程,并控制
ps 命令总在 ls 命令之前执行。
三、实验要求
根据实验中观察和记录的信息结合示例实验和独立实验程序,说明它们反映出操
作系统教材中进程及处理机管理一节讲解的进程的哪些特征和功能?在真实的操作
系统中它是怎样实现和反映出教材中讲解的进程的生命期、进程的实体和进程状态
控制的。你对于进程概念和并发概念有哪些新的理解和认识?子进程是如何创建和
执行新程序的?信号的机理是什么?怎样利用信号实现进程控制?根据实验程序、
调试过程和结果分析写出实验报告。
四、实验步骤
-
打开一终端命令行窗体,新建一个文件夹,在该文件夹中建立以下名为pctl.c
的C语言程序: (调用实例实验代码)
#include “pctl.h”
int main(int argc, char *argv[])
{
int i;
int pid; //存放子进程号
int status; //存放子进程返回状态
char *args[] = {“/bin/ls”,“-a”,NULL}; //子进程要缺省执行的命令
signal(SIGINT,(sighandler_t)sigcat); //注册一个本进程处理键盘中断的函数
pid=fork() ; //建立子进程
if(pid<0) // 建立子进程失败?
{
printf(“Create Process fail!\n”);
exit(EXIT_FAILURE);
}
if(pid == 0) // 子进程执行代码段
{
//报告父子进程进程号
printf(“I am Child process %d\nMy father is %d\n”,getpid(),getppid());
pause(); //暂停,等待键盘中断信号唤醒
//子进程被键盘中断信号唤醒继续执行
printf(“%d child will Running: \n”,getpid()); //
if(argv[1] != NULL){
//如果在命令行上输入了子进程要执行的命令
//则执行输入的命令
for(i=1; argv[i] != NULL; i++) printf(“%s “,argv[i]);
printf(”\n”);
//装入并执行新的程序
status = execve(argv[1],&argv[1],NULL);
}
else{
//如果在命令行上没输入子进程要执行的命令
//则执行缺省的命令
for(i=0; args[i] != NULL; i++) printf(“%s “,args[i]);
printf(”\n”);
//装入并执行新的程序
status = execve(args[0],args,NULL);
}
}
else //父进程执行代码段
{
printf(“\nI am Parent process %d\n”,getpid()); //报告父进程进程号
if(argv[1] != NULL){
//如果在命令行上输入了子进程要执行的命令
//则父进程等待子进程执行结束
printf(“%d Waiting for child done.\n\n”,pid);
waitpid(pid,&status,0); //等待子进程结束
printf(“\nMy child exit! status = %d\n\n”,status);
}
else{
//如果在命令行上没输入子进程要执行的命令
//唤醒子进程,与子进程并发执行不等待子进程执行结束,
if(kill(pid,SIGINT) >= 0)
printf(“%d Wakeup %d child.\n”,getpid(),pid) ;
printf(“%d don’t Wait for child done.\n\n”,getpid());
}
}
return EXIT_SUCCESS;
} -
再建立以下名为 pctl.h 的 C 语言头文件:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<wait.h>
#include<unistd.h>
#include<signal.h>
typedef void(sighandler_t)(int);
void sigcat(){
printf(“%d process continue\n”,getpid());
}
int main(int argc,charargv[])
{int status_1,status_2;
signal(SIGINT,(sighandler_t)sigcat);
char *args1[]={“/bin/ls”,“-a”,NULL};
char *args2[]={“/bin/ps”,“-a”,NULL};
int pid1=fork();
if(pid1<0)
printf(“Create process fail!\n”);
else if(pid1==0)
{
printf(“ls -the child process starting%d\n”,getpid());
pause();
printf(“ls the child process waking%d\n”,getpid());
status_1=execve(args1[0],args1,NULL);
exit(-1);
}
else
{
printf("\n Father Process starting%d\n ",getpid());
int pid2=fork();
if(pid2>0)//只有pid2结束才运行
{
printf("ps the child process over%d\n",pid2);
printf("ls waking%d\n",pid1);
waitpid(pid2,&status_2,0);
kill(pid1,SIGINT);//运行p1
waitpid(pid1,&status_1,0);
printf("ls over%d\n",pid1);
printf("Father process over%d\n",getpid());
exit(-1);
}
else if(pid2<0)
printf(“Process 2fails\n”);
else if(pid2==0)
{
printf("ps starting%d\n ",getpid());
status_2=execve(args2[0],args2,NULL);
}
}
return 0;
}
3) 输入 make 命令编译连接生成可执行的 pctl 程序:
gcc -g -c pctl.c
gcc pctl.o -o pctl
定义重复,只保留pctl.c
五、实验结果
1.输入/pctl指令
2.再次执行带有子进程指定执行命令的 pctl 程序:
$ ./pctl /bin/ls -l
3.查看系统进程
$ ps -l
六、实验小结
通过第一次实验,第一次接触到虚拟机,下载过程中也遇到了很多问题,刚开始使用LINUX环境下的虚拟机,操作中出现了很多问题,但是经过不断的调试,掌握了运行虚拟机程序的基本方法,有利于后续实验的进行。