文章目录
- 信号量定义
- 信号量特性
信号量定义
信号量是一个抽象的数据类型,通常包含一个整数值以及一个等待该值变为正数的任务列表(也称为等待队列)。信号量的整数值代表了系统中某种资源的可用数量。 在操作系统中信号量用于控制对共享资源访问的同步机制。它最初由荷兰计算机科学家Edsger Dijkstra提出,用于解决并发系统中的互斥和同步问题。
简而言之,信号量是用来表示资源的个数。信号量核心就是个计数值。
假如银行能办理业务的窗口只有5个,这里资源数count 指的就是窗口个数5。
- 当窗口没有人办理业务时,count =5 空闲资源;
- 当窗口一有人办理业务,其他窗口没有人办理时,count = count -1 =4 空闲资源;
- 以此类推;
- 当窗口都有人办理时,count =0 ;
- 当窗口都有人办理的同时,入口还有1个人要办理业务,此时该客户处于等待休眠的状态。count = -1 值为负数表示有一个客户在等待;
- 以此类推;
- 当窗口都有人办理的同时,入口有5个人要办理业务,此时这些客户都处于等待休眠的状态。count = -5 值为负数表示有五个客户在等待;
- 当窗口终于有客户办理完业务离开时,count = count +1 = -4,并且唤醒下一位客户到窗口来办理业务。(这里count = -4表明有4个客户在等待)
- 以此类推;
我们通过上面的例子,了解到信号量count的整个过程。使用代码表示上面的过程
int count;void Enter(void) // 入口函数
{if( count > 0 ) // 判断信号量是否大于0{// 有资源count--; // 信号量-1 处理业务 }else{// 没有资源休眠 }
}void Exit(void) // 出口函数
{if( count >= 0 ) // 判断信号量是否大于0{// 没有客户等待count++; // 信号量+1 }else{// count值为负数,有客户在等待唤醒客户count++; }
}
这里count值为全局变量,所有的函数都可以共享。这时系统运行多个任务都要操作count值,就会出现异常。因此在处理函数中不仅需要休眠和唤醒任务,还需要保护count值。
信号量特性
信号量是一种用于多任务环境中协调任务和同步共享资源访问的机制。以下是信号量的主要特性:
1、原子性(Atomicity):
信号量的操作(P操作和V操作)必须是不可分割的,即在执行过程中不能被其他任务中断。这是通过使用原子操作或中断禁用来保证的。
2、有界性(Boundedness):
计数信号量的值不能无限增长,它必须有一个上限,这个上限通常等于系统中某种资源的总数。这可以防止产生无效的资源请求。
3、限制性(Limitation):
信号量的值不能小于0。如果信号量的值已经为0,任何试图执行P操作的任务都将被阻塞,直到信号量的值变为正数。
4、互斥性(Mutual Exclusion):
信号量可用于确保多个任务不会同时访问同一资源。这是通过二值信号量实现的,其值在0和1之间切换,表示资源是否被占用。
5、同步性(Synchronization):
信号量允许任务之间的协调,使得任务可以按照特定的顺序执行。例如,在生产者-消费者问题中,信号量可以用来同步生产者生产数据和消费者消费数据的速率。
6、优先级继承(Priority Inheritance):
为了防止优先级反转问题,当一个低优先级的任务持有信号量而一个高优先级的任务需要该信号量时,低优先级任务可能会临时继承高优先级任务的优先级。
7、死锁避免(Deadlock Avoidance):
信号量的设计和使用需要考虑到死锁的可能性。死锁发生在两个或多个任务无限期地等待对方释放资源。通过适当的设计,如资源分配图算法,可以避免死锁。
8、资源分配策略(Resource Allocation Strategy):
信号量的实现可能包括特定的资源分配策略,如先进先出(FIFO)或优先级队列,以决定唤醒等待资源的任务的顺序。
9、系统调用(System Call):
信号量操作通常通过系统调用实现,这些调用提供了与操作系统内核交互的接口,允许用户空间的任务执行信号量操作。
10、任务调度(Task Scheduling):
信号量与任务调度紧密相关。当一个任务释放信号量时,操作系统的调度器可能需要决定哪个任务应该获得CPU以继续执行。
11、可重入性(Reentrancy):
信号量机制本身应该是可重入的,即一个任务可以多次请求同一信号量,只要它在每次请求之间正确地释放信号量。
12、错误处理(Error Handling):
信号量操作可能需要错误处理机制,以处理如信号量不存在或资源不可用等异常情况。