Loading

16-信号量机制

信号量机制

引例

  1. 进程互斥的四种软件实现方法:
    1. 单标志法
    2. 双标志先检查法
      1. 进入区“检查”,上锁指令无法一气呵成,从而导致了所有进程都有可能进入临界区的问题
    3. 双标志后检查法
    4. Peterson算法
  2. 进程互斥的三种硬件实现方法:
    1. 中断屏蔽方法
    2. TS/TSL指令
    3. Swap/XCHG指令
  3. 所有的解决方法都无法实现“让权等待”
  4. 1965年,荷兰学者Dijsktra提出了一种桌有成效的进程互斥、同步方法–信号量机制

信号量机制

用户进程可以通过操作系统提供的一对原语来对信号量进程操作,从而很方便的实现了进程互斥、进程共享。
信号量其实就是一个变量(可以是一个整数,也可以是记录型变量可以一个信号量表示系统中某种资源的梳理。
软件解决方法的主要问题"是进入区的各个操作无法一气呵成",因此如果能把进入区、退出区的操作都用原语实现,使得操作能“一气呵成”就能避免问题。
信号量原语
一对原语:wait(S)和signal(S)原语,可以把原语理解为我们自己写的函数,函数名分别为wait和signal,括号里的信号量S其实就是函数调用时传入的一个参数。
wait,signal原语简称P,V操作,因此做题时候常把wait(S),signal(S)两个操作分别写为P(S),V(S)
0

整型信号量

用一个整型的变量作为信号量,用来表示系统中某种资源的数量

示例代码

初始化代码
int S=1;
void wait(int S){ //wait原语,相当于进入区
	while(S<=0);  //如果资源数量不够,就一直循环等待
	S=S-1;        //如果资源数量够,则占用一个资源
}
void signal(int S){//Signal原语,相当于退出区
	S=S+1;         //使用完资源后,在退出区释放资源
}
进程代码
wait(S); //进入区,申请资源
使用打印机资源;//临界区,访问资源
signal(S); //退出区,释放资源

存在的问题

  1. 与普通整数变量的区别,即对信号量的操作只有三种,即初始化,P操作,V操作。
  2. “检查”和“上锁”一气呵成,避免了并发,异步导致的问题。
  3. 存在的问题:不满足“让权等待”,会发生忙等。

记录型信号量

整型信号量存在的缺陷是忙等问题,因此人们又提出“记录型信号量”,即用数据结构表示信号量

示例代码

初始化代码

/*记录型信号量的定义*/
typedef struct{
	int value;        //剩余资源数
	struct process *L;//等待队列
}sempahore;

原语操作代码

void wait(semaphore S){
 S.value--;
 if(S.value <0){
	 block(S.L);
	//如果剩余资源数不够,就会使用Block原语,使得进程从运行态进入阻塞态,并把挂到信号量S的等待队列中.
 }
}
void signal(semaphore S){
 S.value++;
 if(S.value<=0){
	 wakeup(S.L);
	 //释放资源后,若还有别的进程在等待这种资源,则使用wakeup原语唤醒队列中的一个进程,改进程从阻塞态变为就绪态。
 }
}
  1. 对信号量S的一次P操作意味着请求一次资源,所以Value减一如果value<0时候表示资源已经分配完毕,应该用block原语进行自我阻塞(当前进程的状态从运行态到阻塞态),主动放弃处理机,并插入该类资源的等待队列S.L中,该机制遵循了“让权等待”原则。
  2. 对信号量S的一次V操作意味着释放一次资源,所以Value加1,如果加1后仍然S<=0,表示仍有进程等待该资源,因此应该用wakeup原语唤醒等待队列中的第一个进程。
posted @ 2023-01-20 11:26  nliuc  阅读(116)  评论(0编辑  收藏  举报