初识多进程


前言


提示:以下是本篇文章正文内容

一、CPU工作原理

CPU工作原理很简单,就是不断的取指执行。CPU根据PC寄存器中的值到内存中取指令,PC会自动+1,当执行完本条指令后,CPU又根据PC寄存器取指执行。

所以我们让CPU执行一段程序最直接的做法就是让PC的值设置为程序的起始地址,这样CPU会自动的执行这段程序直到程序结束。

CPU的工作原理:取指执行(自动的取指执行)

但是如果我们不对CPU进行管理,会导致CPU的利用率较低。

int main(int argc, char* argv[])
{
	int i , to, *fp, sum = 0;
	to = atoi(argv[1]);
	for(i=1; i<=to; i++)
	{
		sum = sum + i;
		fprintf(fp,%d”, sum);
	}
}
//执行时间为 0.30521424865722897

int main(int argc, char* argv[])
{
	int i , to, *fp, sum = 0;
	to = atoi(argv[1]);
	for(i=1; i<=to; i++)
	{
		sum = sum + i;
	}
}
//执行时间为: 0.006346824075317383

从上面可以看到相同的循环次数,但IO任务的执行时间远远大于计算任务,但在执行IO任务时,CPU是空闲的,此时CPU利用率很低。我们可以让CPU在这段时间里忙碌起来,这就要我们对CPU进行管理。

当将PC的值设置为程序的起始地址,如果不对CPU进行管理,让CPU自动的取指执行,如果程序有大量的IO任务时,CPU的利用率极低,所以我们要对CPU进行管理,提高CPU的利用率

CPU管理

当在执行IO任务时,此时CPU处于空闲状态,我们可以将CPU分配给其他程序使用,当IO任务完成时,CPU又切换到该程序继续执行。

管理:核心是任务的切换,内存存放多个程序,多个程序交替执行

CPU的利用率将会提高:
在这里插入图片描述
任务切换:当一个程序执行IO任务时,把PC的值设置为另一个程序的执行地址就可以去执行另一个程序,然后IO任务完成,又切回原来的程序执行
在这里插入图片描述
但是,如何在让CPU切换回来呢?
运行中的程序会有一个称为PCB的数据结构,这个数据结构是用来记录当前程序运行的状态信息的,在进行任务切换时,将一些必要的信息压栈(如CS,IP),然后要切换回来时,出栈(恢复成切换任务前的状态),即可以让当前PC指针指向原来的程序位置,继续运行。

二、多进程

1.引入进程

进程:进程是进行(执行) 中的程序(CPU的管理是为了提高CPU的利用率,提高的核心思想就是多道程序交替执行,为了实现多道程序交替执行,通过进程来管理程序的运行)

进程和程序区别:

1.进程是有状态的。有开始、结束等运行状态,而程序没有。
2.进程会记录一些寄存器的值,这些值就是上下文。
3.进程会走走停停,程序没有这个概念。

2.多进程

多进程图像:启动多个程序,交替执行,能充分利用CPU,启动了的的程序就是进程,多个进程的推进,操作系统只要把这些进程记录好,按照合理的次序推进(分配资源,进行调度)

多进程图像一直存在于操作系统启动到关机的整个过程中

操作系统在启动时开的第一个进程是shell或者windows桌面,shell再启动其他进程

启动shell程序:

//一个命令启动一个进程, 返回shell再启动其他进程
int main(int argc, char * argv[])
{ 
	while(1) 
	{ 
		scanf(%s”, cmd);
		if(!fork()) 
		{ 
			exec(cmd);
		} 
		wait(); 
	}
}

shell程序中在等待输入命令(CMD),有命令输入后就启动该命令对应的进程,然后返回shell再等待启动其他进程。如下图所示:
在这里插入图片描述

3.多进程的组织

多进程的组织:PCB + 状态 + 队列

每个进程都有个PCB(progress control block)来记录该进程的信息,操作系统依赖PCB来感知该进程,通过对PCB的感知将进程排入不同的队列,放在不同的状态中。如图
在这里插入图片描述

三种不同的队列分别对应==运行态、就绪态、阻塞态。==操作系统控制进程在不同状态间切换将他们同时推进。形成如下状态图
在这里插入图片描述
多进程的交替

多进程交替: 队列操作+调度+切换

启动磁盘的读写为例:

启动磁盘读写;
pCur.state = ‘W’;
将pCur放到DiskWaitQueue(磁盘等待队列);
schedule();

schedule()
{
	pNew = getNext(ReadyQueue);
	switch_to(pCur,pNew);
}

pCur是PCB的里面的信息,w表示阻塞态。先将当前进程的状态置为阻塞态,将该进程放进磁盘等待队列。然后启动调度函数(schedule)来切换到下一个进程,其中getnext就是从就绪队列中取下一个将要执行的进程,switch完成切换

进程切换

//上下文切换
switch_to(pCur,pNew) 
{
	//保存正在进行的程序
	pCur.ax = CPU.ax;
	pCur.bx = CPU.bx;
	...
	pCur.cs = CPU.cs;
	pCur.retpc = CPU.pc;

	//将要运行的程序压入CPU中
	CPU.ax = pNew.ax;
	CPU.bx = pNew.bx;
	...
	CPU.cs = pNew.cs;
	CPU.retpc = pNew.pc; 
}

在这里插入图片描述
保存当前现场,恢复下个程序的现场然后执行下个程序。

4.多进程的影响

1.内存管理
由于内存中同时存在多个进程的,多个进程在交替,那么如图中进程1在访问地址100,而地址一百正是进程2开始的地方,进程2很可能还没有完成,就切到了进程1,如果在进程1中地址100处的内容被修改了,那么切回进程2时程序就出错了。
在这里插入图片描述
解决的办法:限制对地址100的读写

多进程的地址空间分离:内存管理的主要内容
通过进程的地址映射实现进程间的地址空间分离
在这里插入图片描述
进程1的映射表将访问限制在进程1范围内,进程1根本访问不到其他进程的内容。也就是[100]只是逻辑上的地址,其对应一篇内存上的物理地址,即使不同进程间都有逻辑地址100,但其对应的物理空间不同

2.多进程合作

打印任务1看到就绪队列空了后,就把自己放了进去,这时打印任务2也看了就绪队列空了,也想把自己放进去,此时任务1还没放完,进插入了任务2,那么7上同时由两个任务的内容,打出来不就是乱码
在这里插入图片描述
所以,在处理共享资源时,可以给共享的资源进行上锁。等待该资源被开锁,下一个进程才能使用


总结

提示:这里对文章进行总结:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super.Bear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值