进程管理(2)
-
同步
若干合作进程为了完成一个共同的任务,需要相互协调允许步伐,一个进程开始某个操作之前必须要求另一个进程已经完成某个操作,否则前面的进程只能等待。
合作进程中某些操作之间需要满足某种先后关系或某个操作能否进行需要满足某个前提条件,否则只能等待。 -
互斥
互斥关系属于同步的一种特殊情况
多个进程由于共享了独占性资源,必须协调各进程对资源的存取顺序:确保没有任何两个或以上的进程同时进行存取操作
互斥与资源共享相关,资源为临界资源,存取操作区域为临界区 -
信号灯机制
信号灯是一种卓有成效的进程同步机制
进程在允许过程受信号灯状态控制(信号灯的状态可用阻塞和唤醒进程),并能改变信号灯状态(信号灯的状态可被进程改变)
信号等数据结构
信号灯变量为一个二元矢量(S,q),S又称信号量,为整数,初值非负,q为PCB队列,初值为空集。 -
P-V操作P(S,q),V(S,q)
P,V为荷兰语Passeren通过,Vrijgeven释放
P操作 | V操作 |
---|---|
S值减1 | S值加1 |
若差大于或等于零,该进程继续 | 若和大于零,该进程继续 |
若差小于零,则该进程阻塞并加入队列q中,转入调度函数 | 若和小于或等于零,该进程继续同时从q中唤醒一个进程 |
可能阻塞当前进程 | 可能唤醒阻塞进程 |
- P-V操作解决互斥问题
实现对临界区的互斥访问,允许最多一个进程处于临界区
S值的设置要合理
临界区 | P-V操作 | 锁机制 |
---|---|---|
进入 | 先执行P操作 | 先执行上锁操作 |
离开 | 后执行V操作 | 后执行开锁操作 |
-
P-V操作解决同步问题
运行条件不满足时,能让进程暂停,运行条件满足时,能让进程立即继续。
基本思路:在关键操作之前执行P操作,必要时可阻塞进程;在关键操作之后执行V操作,必要时唤醒合作进程。
S值得设置要合理
S值为当前资源可用的个数,可能是资源拥有量也可能是资源空缺量 -
经典同步问题
-
生存者消费者问题,一群生产者向一群消费者提出产品(数据),共享缓冲区
不能向满缓冲区存产品
不能从空缓冲区取产品
每个时刻仅允许1各生产者或消费者存或取产品 -
读者和编者问题,有一本书,有多个读者读书,有多个编者编书
允许多个读者同时读
不允许读者、编者同时操作
不允许多个编者同时操作 -
Windows进程同步机制
-
临界区(CRITICAL SECTION),在进程内使用,保证仅一个线程申请到该对象,临界区内是临界资源的访问。
相关API:
InitializeCriticalSection,初始化
DeleteCriticalSection,删除
EnterCriticalSection,进入(相当于P操作)
LeaveCriticalSection,退出(相当于V操作) -
等待函数,等待目标对象编程有信号的状态就返回
WaitForMultipleObjects,等待多个目标
WaitForSingleObject,等待单个目标 -
互斥量
保证只有一个线程或进程可以申请该对象,可以跨进程使用,可以有名称,互斥量比临界区耗费更多资源,速度慢 -
信号量
允许指定数目的多个线程/进程访问临界区
一种资源计数器,用于限制并发线程的数量
初始值可设为N,表示允许N个进程/线程并发访问资源
相关API:
CreateSemaphore,创建
OpenSemaphore,打开
ReleaseSemaphore,释放
CloseSemaphore,关闭 -
信号量的值可通过相应函数增加或减少,WaitForSingleObject将信号量减1,ReleaseSemaphore将信号量增1
-
信号量的值大于0时,为有信号状态;信号量的值小于等于0时,为无信号状态。
Windows同步机制 | PV操作 |
---|---|
临界区对象 | |
EnterCriticalSection | P操作 |
LeaveCriticalSection | V操作 |
互斥量对象 | |
ReleaseSemaphore | V操作 |
事件对象 | |
SetEvent | V操作 |
信号量对象 | |
CreateSemaphore | |
ReleaseSemaphore | V操作 |
等待机制 | |
WaitForSingleObject | P操作 |
-
Linux父子进程同步
wait(status):进程调用wait阻塞自己,阻塞到有子进程结束,或有僵尸进程(wait收集该子进程信息并彻底销毁它后返回)
status保存进程退出时的状态,可用wait(Null)忽略退出信息。
exit(status):进程终结时要释放资源并报告父进程
利用status传递including结束时的状态
变为僵尸状态,保留部分PCB信息供wait收集,包含正常结束或异常结束,占有总系统cpu事件,缺页中断次数
调用schedule函数,选择新进程运行
sleep(nSecond):进程暂停执行nSecond秒,系统暂停调度该进程,相当于windows的suspend,挂起若干秒 -
父子进程对普通变量的共享,是独立的不同变量副本操作
-
父子进程对文件资源的共享,共同使用同一文件和读写指针
-
匿名管道通信
管道是进程间的一种通信机制,一个进程可通过管道将数据传递给另一个进程,前者向管道输入数据,后者从管道读取数据。 -
管道像文件一样,可读可写
CreartePipe(Handle W, Handle R) 创建管道同时创建读写句柄
通过写写句柄(W)向管道中写数据,WriteFile(W, Buffer)或通过输出重定向向写句柄(W)写入
通过读读句柄(R)从管道中读数据,ReadFile(R, Buffer)或通过输入重定向向读句柄(R)读取。 -
仅能用于父子或兄弟进程进行通信,由父进程创建管道和子进程,父进程写或读管道,子进程则输入或输出重定向到管道。父进程创建子进程时,需要将子进程的输入输出进行重定向到管道
-
双向通信必须建立2个管道
-
Linux信号通信
信号是Linux进程间一种重要的通信机制
信号是向进程发送的一个通知,通知某个事件已发生。收到信号的进程可用立即执行指定的操作,信号的发出可用是进程,也可以是系统(含硬件)
操作 | 信号 | 效果 |
---|---|---|
键盘Ctrl + C | SIGINT信号 | 结束进程 |
键盘Ctrl + Z | SIGSTP信号 | 挂起进程 |
终端kill -9 | SIGKILL信号 | 强制结束进程 |
- 信号产生方式
1.键盘输入特殊组合键产生信号
2.执行终端命令产生信号
3.程序中调用函数产生信号
4.硬件异常或内核产生相应信号
*Linux定义了64=2^6种信号,用整数1~64表示
信号编号 | 信号名称 | 说明 |
---|---|---|
2 | SIGINT | 进程结束 |
6 | SIGABRT | 进程结束 |
9 | SIGKILL | 进程强制结束,用户不能获取该信号 |
11 | SIGUSR1 | 用户定义信号1 |
14 | SIGALRM | 定时器时间的信号 |
19 | SIGSTP | 进程挂起 |
- 注册信号处理函数signal()
为指定信号注册信号处理函数,当进程收到该信号时,立即执行相应操作。一般在进程初始化时使用该函数注册信号处理函数 - 发送信号函数kill()
向目标进程发生信号