【操作系统】实验二:进程的控制【完整版实验报告】

实验二:进程的控制

1 .实验目的
通过进程的创建、撤消和运行加深对进程概念和进程并发执行的理解,明确进程与程序之间的区别。
【答:进程概念和程序概念最大的不同之处在于:
(1)进程是动态的,而程序是静态的。
(2)进程有一定的生命期,而程序是指令的集合,本身无“运动”的含义。没有建立进程的程序不能作为1个独立单位得到操作系统的认可。
(3)1个程序可以对应多个进程,但1个进程只能对应1个程序。进程和程序的关系犹如演出和剧本的关系。
(4)进程和程序的组成不同。从静态角度看,进程由程序、数据和进程控制块(PCB)三部分组成。而程序是一组有序的指令集合。】

2 .实验内容
(1) 了解系统调用fork()、execvp()和wait()的功能和实现过程。
(2) 编写一段程序,使用系统调用fork()来创建两个子进程,并由父进程重复显示字符串“parent:”和自己的标识数,而子进程则重复显示字符串“child:”和自己的标识数。
(3) 编写一段程序,使用系统调用fork()来创建一个子进程。子进程通过系统调用execvp()更换自己的执行代码,新的代码显示“new program.”。而父进程则调用wait()等待子进程结束,并在子进程结束后显示子进程的标识符,然后正常结束。

3 .实验步骤
(1)gedit创建进程1.c
(2)使用gcc 1.c -o 1编译并./1运行程序1.c
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
void mian(){
int id;
if(fork()==0)
{printf(“child id is %d\n”,getpid());
}
else if(fork()==0)
{printf(“child2 id %d\n”,getpid());
}
else
{id=wait();
printf(“parent id is %d\n”,getpid());
}
}
在这里插入图片描述

(3)运行并查看结果
child’s pid=2894
child’s pid=2994
parent’s pid=2849
child’s pid=2897
child’s pid=2897
parent’s pid=2849
child’s pid=2894
child’s pid=2994
parent’s pid=2849

(4)gedit创建进程2.c
使用gcc 2.c -o 2编译并./2运行程序2.c#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
pid_t pid;
char *a[]={“ls”,"-l","/etc/passwd",0};
int result;
pid=fork();
if(pid<0){
printf(“frok error!”);}
else if(pid==0){
printf(“new program !\n”);
execvp(“ls”,a);
exit(0);
}
else{
int e=waitpid(pid,&result,0);
printf(“child peocess PID:%d\n”,e);
exit(0);
}
}
(5)在这里插入图片描述

(6)运行并查看结果
new program !
-rw-r–r--. 1 root root 2456 Apr 14 2019 /etc/passwd
child peocess PID:29035

4 .思考
(1) 系统调用fork()是如何创建进程的?
【答:(1)申请空白PCB
(2)为新进程分配资源
(3)初始化进程控制块
(初始化标识信息,初始化处理机状态信息,初始化处理机控制信息,)
(4)将新进程插入就绪队列】
(2)当首次将CPU 调度给子进程时,其入口在哪里?
【答:进程的进程控制块(PCB)结构中有指向其TTS(任务状态段)的指针, TTS里面存放着进程的入口。】
(3)系统调用execvp()是如何更换进程的可执行代码的?
【答:一个库函数通过调用execve来调用内核服务来执行指明的程序】
(4) 对一个应用,如果用多个进程的并发执行来实现,与单个进程来实现有什么不同?
【答:相对于单个进程而言,程序并发执行就是系统中的各个部分不再以单纯串行方式工作,在同一时刻系统中不是只有一个活动,而是存在许多并行活动。并且充分利用多核CPU的计算能力,方便进行业务拆分,提升应用性能。其次,时间片是CPU分配给各个线程的时间,因为时间非常短,所以CPU不断通过切换线程,让我们觉得线程是同时执行的,时间片一般是几十毫秒.而每次切换时,需要将当前的状态保存起来,以便能够进行恢复先前的状态,而这个切换是非常消耗性能的,过于频繁的切换反而无法发挥出多线程编程的优势.最后,因为单进程不会和其它进程争用竟源,也不会和其它进程有什么执行顺序不合理导理死锁,多进程并不仅发失去其封闭性并且会导致死锁现象】

  • 28
    点赞
  • 216
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
(1)进程的软中断通信 #include #include #include #include int wait_flag; void stop(); main( ) { int pid1, pid2; // 定义两个进程号变量 signal(2,stop); // 或者 signal (14,stop); while((pid1 = fork( )) == -1); // 若创建子进程1不成功,则空循环 if(pid1 > 0) { // 子进程创建成功,pid1为进程号 while((pid2 = fork( )) == -1); // 创建子进程2 if(pid2 > 0) { wait_flag = 1; //sleep(1); // 父进程等待5秒 kill(pid1,SIGUSR1); // 杀死进程1 kill(pid2,SIGUSR2); // 杀死进程2 wait(0); wait(0); printf("\n Parent process is killed !!\n"); exit(0); // 父进程结束 } else { wait_flag = 1; signal(SIGUSR2,stop); // 等待进程2被杀死的中断号17 printf("\n Child process 2 is killed by parent !!\n"); exit(0); } } else { wait_flag = 1; signal(SIGUSR1,stop); // 等待进程1被杀死的中断号16 printf("\n Child process 1 is killed by parent !!\n"); exit(0); } } void stop() { wait_flag = 0; } (2)进程的管道通信 #include #include #include int pid1,pid2; // 定义两个进程变量 main( ) { int fd[2]; char OutPipe[100],InPipe[100]; // 定义两个字符数组 pipe(fd); // 创建管道 while((pid1 = fork( )) == -1); // 如果进程1创建不成功,则空循环 if(pid1 == 0) { lockf(fd[1],1,0); // 锁定管道 sprintf(OutPipe,"\n Child process 1 is sending message!\n"); write(fd[1],OutPipe,50); // 向管道写入数据 sleep(5); // 等待读进程读出数据 lockf(fd[1],0,0); // 解除管道的锁定 exit(0); // 结束进程1 } else { while((pid2 = fork()) == -1); // 若进程2创建不成功,则空循环 if(pid2 == 0) { lockf(fd[1],1,0); sprintf(OutPipe,"\n Child process 2 is sending message!\n"); write(fd[1],OutPipe,50); sleep(5); lockf(fd[1],0,0); exit(0); } else { wait(0); // 等待子进程1 结束 read(fd[0],InPipe,50); // 从管道中读出数据 printf("%s\n",InPipe); // 显示读出的数据 wait(0); // 等待子进程2 结束 read(fd[0],InPipe,50); printf("%s\n",InPipe); exit(0); // 父进程结束 } } }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值