操作系统 进程管理问题实现(使用linux系统)

进程管理是操作系统重要的内容之一,下面给出进程管理实例实现。

实现内容
(1)进程的创建
编写一段程序,使用系统调用fork() 创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”,子进程分别显示字符“b”和“c”。试观察记录屏幕上的显示结果,并分析原因。

(2)进程的控制
修改已经编写的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。
如果在程序中使用系统调用lockf () 来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。

(3)①编写一段程序,使其现实进程的软中断通信。
要求:使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按DEL键);当捕捉到中断信号后,父进程用系统调用Kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:
Child Processll is Killed by Parent!
Child Processl2 is Killed by Parent!
父进程等待两个子进程终止后,输出如下的信息后终止
Parent Process is Killed!
②在上面的程序中增加语句signal (SIGNAL, SIG-IGN) 和signal (SIGQUIT, SIG-IGN), 观察执行结果,并分析原因。

实现上述内容,进行算法分析(每一个小括号对应一个实现):
(1)分析:从进程并发执行来看,输出bac ,acb等情况都有可能。原因:fork()创建进程所需的时间要多于输出一个字符的时间,因此在主进程创建进程2的同时,进程1就输出了“b”,而进程2和主程序的输出次序是有随机性的,所以会出现上述结果。

(2)分析:由于函数printf()输出的字符串之间不会被中断.因此,字符串内部的字符顺序输出时不变。但是,由于进程并发执行时的调度顺序和父子进程的抢占处理机问题,输出字符串的顺序和先后随着执行的不同而发生变化。这与打印单字符的结果相同。

(3)上述程序中,实用函数signal()都放在一段程序的前面部位,而不是在其他接收信号处。这是因为signal()的执行只是为进程指定信号量16或17的作用,以及分配相应的与.stop( )过程链接的指针。从而,signal( )函数必须在程序前面部分执行。

(4)由于忽略了中断与退出信号,程序会-直保持阻塞状态而无法退出。分析:从进程并发执行来看,输出bac ,acb等情况都有可能。原因:fork()创建进程所需的时间要多于输出一个字符的时间,因此在主进程创建进程2的同时,进程1就输出了“b”,而进程2和主程序的输出次序是有随机性的,所以会出现上述结果。

给出(2)进程控制的实现结果:
在这里插入图片描述
由于函数printf()输出的字符串之间不会被中断,因此,每个字符串内部的字符顺序输出时不变。但是,由于进程并发执行时的调度顺序和父子进程的抢占处理机问题,输出字符串的顺序和先后随着执行的不同而发生变化。这与打印单字符的结果相同。

在这里插入图片描述
进程互斥的原因是存在两个或两个以上的进程,不能同时进入同一组共享变量的临界区域,否则可能会发生与时间相关的错误,而lockf()函数是将文件区域用作信号量(监视锁),或控制对锁定进程的访问,试图访问已锁定资源的其他进程将返回错误或者进入休态,直到资源解除锁定为止,但以上三个进程在( lockf(1,1,0)锁定标准输出设备,lockf(1,0,0)解锁标准输出设备)lockf(1,1,0)与lockf(1,0,0)中间的for循环不存在共享变量的临界区域,因此输出和原来是一样的。

给出(3)软中断实现:
在这里插入图片描述
软中断一般是指由指令int引起的“伪”中断动作——给CPU制造一个中断的假象。Signal函数的原型为:signal(sig,function),它以软中断信号的序号作为参数调用函数,也就是说,收到软中断信号sig后,调用函数function,当子进程1收到进程中断信号16后,调用stop()解除“waiting”,继续往下执行;当进程1打印完句子后就会退出,对于子进程2来说也是这样的。但是父进程在此阶段一直处于“waiting”状态(执行(wait(0)),直到两个子进程都退出后,父进程才会退出。
由于ctrl+c信号会并发传到每个进程中,进程受到该信号会立刻终止。当子进程收到ctrl+c信号时,就终止了,根本不会等父进程传来的软中断信号,因此也就不会打印出child processl1 is killed和child processl2 is killed.

在这里插入图片描述
signal(SIGINT, SIG-IGN)和signal(SIGQUIT, SIG-IGN)的作用是屏蔽从键盘上传来的中断信号,因此子进程可以接收到父进程传来的软中断信号,进而将那两句话打印出来。

最后给出实现源码(博主使用putty完成本次实验,使用gcc等指令)
一、进程管理

#include<unistd.h>
#include<math.h>
#include<stdio.h>
void main(void){
	int p1,p2,i;
	if((p1=fork())==-1){printf("Fork Error/n");}
	else if(p1==0){
		printf("b");
	}
	else{
		if((p2=fork())==-1){printf("Fork Error/n");}
		else if(p2==0)printf("c");
		else{
			printf("a");
		}
	}
}

二、进程控制
程序一:

#include<unistd.h>
#include<math.h>
#include<stdio.h>
void main(void){
	int p1,p2,i;
	if((p1=fork())==-1){printf("Fork Error/n");}
	else if(p1==0){
		for(i=0;i<3;i++)
			printf("daughter:%d\n",i);
	}
	else{
		if((p2=fork())==-1){printf("Fork Error/n");}
		else if(p2==0){		
		for(i=0;i<3;i++)
			printf("son:%d\n",i);
		}else{
		for(i=0;i<3;i++)
			printf("parent:%d\n",i);
		}
	}
}

程序二:

#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<math.h>
#include<stdio.h>
#include<fcntl.h>
#include<errno.h>
#include<signal.h>
#include<stdlib.h>
void main(void){
	pid_t p1,p2;
	int i;
	p1=fork();
	if(p1<0){
		printf("Fork Error/n");
		exit(-1);
	}
	else if(p1==0){
		lockf(1,1,0);
		for(i=0;i<3;i++)
			printf("daughter:%d\n",i);
		lockf(1,0,0);
		exit(0);
	}
	else{
		p2=fork();
		if(p2==-1){
			printf("Fork Error/n");
			exit(-1);
		}
		else if(p2==0){
		lockf(1,1,0);  /*加锁*/		
		for(i=0;i<3;i++)
			printf("son:%d\n",i);
		lockf(1,0,0);	/*解锁*/
		exit(0);
		}else{
		lockf(1,1,0);  /*加锁*/	
		for(i=0;i<3;i++)
			printf("parent:%d\n",i);
		lockf(1,0,0);	/*解锁*/
		exit(0);
		}
	}
}

三、
1、

#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<math.h>
#include<stdio.h>
#include<fcntl.h>
#include<errno.h>
#include<signal.h>
#include<stdlib.h>
int w;
void waiting()
{
	while(w!=0);
}
void stop()
{
	w=0;
}
void main(void){
	pid_t p1,p2;
	p1=fork();
	if(p1<0){
		printf("Fork Error/n");
		exit(-1);
	}
	else if(p1==0){
		w=1;
		signal(16,stop);
		waiting();
		lockf(1,1,0);
		printf("Child Processl1 is killed by Parent!\n");
		lockf(1,0,0);
		exit(0);
	}
	else{
		p2=fork();
		if(p2==-1){
			printf("Fork Error/n");
			exit(-1);
		}
		else if(p2==0){
		w=1;
		signal(17,stop);
		waiting();
		lockf(1,1,0);  /*加锁*/		
		printf("Child Processl2 is killed by Parent!\n");
		lockf(1,0,0);	/*解锁*/
		exit(0);
		}else{
		w=1;
		signal(SIGINT,stop);//获取到键盘上传来的信号,执行stop函数
		waiting();
		kill(p1,16);//向子进程p1发送软中断信号16
		kill(p2,17);//向子进程p2发送软中断信号17
		wait(0);
		wait(0);
		printf("Partent Process is killed!\n");
		exit(0);
		}
	}
}}

2、

int w;
void waiting()
{
	while(w!=0);
}
void stop()
{
	w=0;
}
void main(void){
	pid_t p1,p2;
	//signal(SIGINT,SIG_IGN);
	//signal(SIGQUIT,SIG_IGN);
	p1=fork();
	if(p1<0){
		printf("Fork Error/n");
		exit(-1);
	}
	else if(p1==0){
		w=1;
		signal(16,stop);
		signal(SIGINT,SIG_IGN);
		waiting();
		lockf(1,1,0);
		printf("Child Processl1 is killed by Parent!\n");
		lockf(1,0,0);
		exit(0);
	}
	else{
		p2=fork();
		if(p2==-1){
			printf("Fork Error/n");
			exit(-1);
		}
		else if(p2==0){
		w=1;
		signal(17,stop);
		signal(SIGINT,SIG_IGN);
		waiting();
		lockf(1,1,0);  /*加锁*/		
		printf("Child Processl2 is killed by Parent!\n");
		lockf(1,0,0);	/*解锁*/
		exit(0);
		}else{
		w=1;
		signal(SIGINT,stop);//获取到键盘上传来的信号,执行stop函数
		waiting();
		kill(p1,16);//向子进程p1发送软中断信号16
		kill(p2,17);//向子进程p2发送软中断信号17
		wait(0);
		wait(0);
		printf("Partent Process is killed!\n");
		exit(0);
		}
	}
}
  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值