进程同步、进程通信和进程状态

进程同步

背景:多进程虽然提高了系统资源利用率和吞吐量,但是由于进程的异步性可能造成系统的混乱。进程同步的任务就是对多个相关进程在执行顺序上进行协调,使并发执行的多个进程之间可以有效的共享资源和相互合作,保证程序执行的可再现性。

 

1、信号量(用于互斥):

        用于进程间传递信号的一个整数值。在信号量上只有三种操作可以进行:初始化,P操作(-)和V操作(+),这三种操作都是原子操作。P操作(-)可以用于阻塞一个进程,V操作(+)可以用于解除阻塞一个进程。

      可把信号量视为一个具有整数值的变量,在它之上定义三个操作:

      一个信号量可以初始化为非负数

      semWait操作使信号量s减1.若值为负数,则执行semWait的进程被阻塞。否则进程继续执行。

      semSignal操作使信号量加1,若值大于或等于零,则被semWait操作阻塞的进程被解除阻塞。

2、管程:

      信号量机制功能强大,但使用时对信号量的操作分散,而且难以控制,读写和维护都很困难。因此后来又提出了一种集中式同步进程——管程。其基本思想是将共享变量和对它们的操作集中在一个模块中,操作系统或并发程序就由这样的模块构成。这样模块之间联系清晰,便于维护和修改,易于保证正确性。

      从语言的角度看,管程主要有以下特性:

      (1)模块化。管程是一个基本程序单位,可以单独编译;

      (2)抽象数据类型。管程是中不仅有数据,而且有对数据的操作;

      (3)信息掩蔽。管程外可以调用管程内部定义的一些函数,但函数的具体实现外部不可见;

      对于管程中定义的共享变量的所有操作都局限在管程中,外部只能通过调用管程的某些函数来间接访问这些变量。因此管程有很好的封装性。

      为了保证共享变量的数据一致性,管程应互斥使用。 管程通常是用于管理资源的,因此管程中有进程等待队列和相应的等待和唤醒操作。在管程入口有一个等待队列,称为入口等待队列。当一个已进入管程的进程等待时,就释放管程的互斥使用权;当已进入管程的一个进程唤醒另一个进程时,两者必须有一个退出或停止使用管程。在管程内部,由于执行唤醒signal操作,可能存在多个等待进程(等待使用管程),称为紧急等待队列(管程内部的进程执行了wait),它的优先级高于入口等待队列,也就是说,如果紧急队列有进程,则唤醒里面的进程,否则唤醒入口队列的进程。

      因此,一个进程进入管程之前要先申请,一般由管程提供一个enter过程;离开时释放使用权,如果紧急等待队列不空,则唤醒第一个等待者,一般也由管程提供外部过程leave。

      管程内部有自己的等待机制。管程可以说明一种特殊的条件型变量:var c:condition;实际上是一个指针,指向一个等待该条件的PCB队列。对条件型变量可执行wait和signal操作:(联系P和V; take和give)

      wait(c):若紧急等待队列不空,唤醒第一个等待者,否则释放管程使用权。执行本操作的进程进入C队列尾部;

      signal(c):若C队列为空,继续原进程,否则唤醒队列第一个等待者,自己进入紧急等待队列尾部。

 

      经典的进程同步问题:生产者-消费者问题;哲学家进餐问题;读者-写者问题

进程通信

      进程间通信主要包括 管道, 系统IPC(包括消息队列,信号量,共享存储), SOCKET.

      管道:为了协调双方的通信,管道机制必须提供以下三方面的协调能力:互斥、同步和确定对方的存在。管道包括以下三种:

      1)普通管道PIPE, 通常有两种限制,一是半双工,只能单向传输;二是只能在父子进程间使用

      2)流管道s_pipe: 去除了第一种限制,可以双向传输

      3)命名管道:name_pipe, 去除了第二种限制,可以在许多并不相关的进程之间进行通讯

 

      系统IPC的三种方式类同,都是使用了内核里的标识符来识别.

 

(1)管道(Pipe):管道是一种半双工的通信方式,可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。

(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令 mkfifo 或系统调用 mkfifo 来创建。

(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux 除了支持 Unix 早期信号语义函数 signal 外,还支持语义符合 Posix.1 标准的信号函数 sigaction(实际上,该函数是基于 BSD的,BSD 为了实现可靠信号机制,又能够统一对外接口,用 sigaction 函数重新实现了 signal函数)。

(4)IPC消息(Message)队列:消息队列是消息的链接表,存放在内核中并由消息队列标识符标识。包括 Posix 消息队列 system V 消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

(5)IPC共享内存:使得多个进程可以访问同一块内存空间,是最快的可用 IPC 形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

(6)IPC信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。

(7)内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。

(8)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由 Unix 系统的 BSD 分支开发出来的,但现在一般可以移植到其它类 Unix 系统上:Linux 和 System V 的变种都支持套接字

 

进程状态

就绪Ready状态:进程已获得除处理机以外的所需资源,等待分配处理机资源

运行Running状态:占用处理机资源运行,处于此状态的进程数小于等于CPU数

阻塞Blocked状态: 进程等待某种条件,在条件满足之前无法执行

(1) 就绪→执行:当前运行进程阻塞,调度程序选一个优先权最高的进程占有处理机;

处于就绪状态的进程,当进程调度程序为之分配了处理机后,该进程便由就绪状态转变成执行状态。

(2) 执行→就绪:当前运行进程时间片用完;

处于执行状态的进程在其执行过程中,因分配给它的一个时间片已用完而不得不让出处理机,于是进程从执行状态转变成就绪状态。

(3) 执行→阻塞:当前运行进程等待键盘输入,进入了睡眠状态;

正在执行的进程因等待某种事件发生而无法继续执行时,便从执行状态变成阻塞状态。

(4) 阻塞→就绪:I/O操作完成,被中断处理程序唤醒。

处于阻塞状态的进程,若其等待的事件已经发生,于是进程由阻塞状态转变为就绪状态。

猜你喜欢

转载自blog.csdn.net/qq_35642036/article/details/82801071