前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多进程的组织、交替、合作

多进程的组织、交替、合作

原创
作者头像
xujjj
修改2019-07-01 10:23:24
4260
修改2019-07-01 10:23:24
举报
文章被收录于专栏:IT界的泥石流IT界的泥石流

1.多进程如何组织?

上文中(操作系统之进程管理(1):从CPU如何执行进程说起),我们说过操作系统为每个程序提供了一个叫做PCB(Process Control Block进程控制块)的数据结构。它记录了该程序执行到什么位置,执行过的值的状态、相关寄存器的状态等信息,供CPU再次返回时恢复现场使用。简单来说,PCB就是操作系统为系统进程提供的一种记录进程信息的数据结构

首先,进程有五种状态,PCB记录了进程处于何种状态。

运行态:该进程正在执行。

(运行态--->阻塞态):

遇到IO操作指令时,执行IO指令(如读写磁盘操作),此时进程进入阻塞态。 

(运行态--->就绪态):

因为CPU是按照时间片在各进程间来回切换使进程共同推进的,因此当前进程CPU在其上的时间片过了之后,当前进程重新进入就绪态,等待下一次CPU的时间片来临。

就绪态:进程已经做好了准备,有机会得到CPU的资源,然后就开始执行变为运行态。(就绪态--->运行态)

阻塞态:进程在某些事情发生时不能被CPU调度,必须等待阻塞进程的事件完成,然后进入就绪态,才有机会得到CPU的调度执行变为运行态。如当前进程处于IO操作,此时进程不能被调度,只有IO操作完成之后,变为就绪态,才有机会被调度。(阻塞态--->就绪态)

新建态:刚刚创建的进程,操作系统还没有把它加入到可执行进程组中,通常是(PCB)进程控制块已经创建但是还没有加载到内存中的进程。

终止态:操作系统从可执行进程组中释放出的进程,或由于自身或某种原因停止运行。

多进程的组织方式?

1.有一个进程在执行(运行态)

2.有一些进程在等待被调度执行(就绪态):

3.有一些进程在等待某事件结束(阻塞态)

2.多进程如何交替

pCur为当前执行的进程,执行启动磁盘读写指令后,把该进程PCB放入DiskWaitQueue,即把该进程放入上述的磁盘等待队列,此时pCur当前进程由运行态转化为阻塞态,然后执行schedule()函数,在就绪队列中找到一个处于就绪状态的进程,切换到该就绪进程使其转化为运行态,得到CPU调度执行该进程。

进程交替(schedule()函数)涉及两部分:

1.pNew = getNext(ReadyQueue),从就绪队列中找一个就绪态进程

那么getNext(ReadyQueue)到底以什么策略在就绪队列中寻找一个处于就绪态的进程去执行呢?

这个问题就属于进程调度的范畴了,该问题目前仍然处于一个热点研究之中,下面我列举两种比较常见的进程调度策略。

FIFO(先进先出):即每次选择进程调度的时候就从就绪队列中拿出队首的进程去调度,而刚转化为就绪态的进程就放进队列的尾部。很显然FIFO是公平的策略,先变为就绪态的在队首,后变为就绪态的在其后,先调度先变为就绪态的,后调度后变为就绪态的。但是FIFO没有考虑进程执行的任务区别,有的进程需要紧急执行的,有的进程不需要那么急执行的,显然FIFO策略做不到这一点。

Priority(优先级):每次选择进程调度的时候从队列中选出需要紧急执行的(优先级高)进程,但是这样的策略有可能会使某些进程饥饿,即优先级低的可能永远都得不到被调度的机会,一直在就绪队列中等待。

2.switch_to(pCur, pNew),从当前进程切换到上步中找到的就绪进程调度执行:

切换的过程即为保存pCur当前进程的信息,方便下次调度时恢复现场,然后恢复pNew即将执行的进程的现场,调度pNew进程。此时就完成了两个进程的切换。

值得一提的是:

switch_to(pCur, pNew)函数的代码必须是汇编代码,因为C代码没法精细控制寄存器。

3.多进程如何合作

看以下有关生产者——消费者实例。

定义一个buffer缓冲区,只能装10个元素,定义两个进程,一个叫生产者进程,一个叫消费者进程,定义一个共享数据counter,记录缓冲区的元素个数,当缓冲区不满时,生产者进程不停地往buffer中塞数据,当缓冲区不空时,消费者进程不停地从buffer中取数据出来。

  图1   生产者往缓冲区塞数据
图1 生产者往缓冲区塞数据
 图2  塞进去了
图2 塞进去了
 图3  消费者从缓冲区取数据
图3 消费者从缓冲区取数据

生产者——消费者代码

初始化生产者进程和消费者进程的共享数据

counter:记录缓冲区元素个数。

流程:

生产者进程——塞数据,counter + +

消费者进程——取数据,counter - -

生产者进程
生产者进程
消费者进程
消费者进程

因为进程是交替执行的,因此一个可能的执行序列为:

如上图代码,假设当前counter=5,生产者往buffer里塞1个,消费者从buffer取1个,按道理最后counter应该还是等于5,但是按如上图操作序列,最后counter的结果等于4,显然这是不对的。

到底为什么呢?

因为生产者和消费者都对共享变量counter进行了操作!当生产者改变了counter值后,但消费者保存着生产者修改前的值而不是生产者修改后的值,因此造成了共享数据的读写紊乱。

解决该问题的核心在于进程同步(需要合理的进程推进顺序)

当某进程读写共享数据counter时将counter锁住自己用,切断其他进程访问共享数据counter。

还是如上的那个可能的执行序列:

当对共享变量counter进行读写操作的时候,给counter上锁,即生产者访问或者修改counter值时,消费者不得访问或修改counter值,反之,消费者访问或者修改counter值时,生产者不得访问或修改counter值,问题得以解决,这就是进程的同步。

以上就是有关多进程的组织、交替、合作的讲解,各位读者大人若有问题,欢迎后台留言,我将第一时间回复!

欢迎关注我们的微信公众号:IT界的泥石流

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.多进程如何组织?
  • 2.多进程如何交替
  • 3.多进程如何合作
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档