Linux信号量之内核信号量

一、内核信号量

Linux内核的信号量在概念和原理上与用户态的System V的IPC机制信号量是一样的,但是它绝不可能在内核之外使用,它是一种睡眠锁。

如果有一个任务想要获得已经被占用的信号量时,信号量会将其放入一个等待队列(它不是站在外面痴痴地等待而是将自己的名字写在任务队列中)然后让其睡眠。

当持有信号量的进程将信号释放后,处于等待队列中的一个任务将被唤醒(因为队列中可能不止一个任务),并让其获得信号量。

这一点与自旋锁不同,处理器可以去执行其它代码。

它与自旋锁的差异:由于争用信号量的进程在等待锁重新变为可用时会睡眠,所以信号量适用于锁会被长时间持有的情况;

相反,锁被短时间持有时,使用信号量就不太适宜了,因为睡眠、维护等待队列以及唤醒所花费的开销可能比锁占用的全部时间表还要长;

由于执行线程在锁被争用时会睡眠,所以只能在进程上下文中才能获得信号量锁,因为在中断上下文中是不能进行调试的;持有信号量的进程也可以去睡眠,当然也可以不睡眠,因为当其他进程争用信号量时不会因此而死锁;不能同时占用信号量和自旋锁,因为自旋锁不可以睡眠而信号量锁可以睡眠。相对而来说信号量比较简单,它不会禁止内核抢占,持有信号量的代码可以被抢占。

信号量还有一个特征,就是它允许多个持有者,而自旋锁在任何时候只能允许一个持有者。

当然我们经常遇到也是只有一个持有者,这种信号量叫二值信号量或者叫互斥信号量。允许有多个持有者的信号量叫计数信号量,在初始化时要说明最多允许有多少个持有者(Count值)
信号量在创建时需要设置一个初始值,表示同时可以有几个任务可以访问该信号量保护的共享资源,初始值为1就变成互斥锁(Mutex),即同时只能有一个任务可以访问信号量保护的共享资源。
当任务访问完被信号量保护的共享资源后,必须释放信号量,释放信号量通过把信号量的值加1实现,如果信号量的值为非正数,表明有任务等待当前信号量,因此它也唤醒所有等待该信号量的任务。

二、内核信号量的构成

内核信号量类似于自旋锁,因为当锁关闭时,它不允许内核控制路径继续进行。当内核控制路径试图获取内核信号量锁保护的忙资源时,相应的进程就被挂起。只有在资源被释放时,进程才再次变为可运行。
只有可以睡眠的函数才能获取内核信号量;中断处理程序和可延迟函数都不能使用内核信号量。 内核信号量是struct semaphore类型的对象,在内核源码中位于include\linux\semaphore.h文件

struct semaphore
{
    
    //相当于信号量的值,大于0,资源空闲;等于0,资源忙,
    //但没有进程等待这个保护的资源;小于0,资源不可用,
    //并至少有一个进程等待资源
   atomic_t count;
   int sleepers;//存放一个标志,表示是否有一些进程在信号量上睡眠
   wait_queue_head_t wait; //存放等待队列链表的地址,当前等待资源的所有睡眠进程都会放在这个链表中
}

三、内核信号量中的等待队列

内核信号量使用了等待队列wait_queue来实现阻塞操作。

当某任务由于没有某种条件没有得到满足时,它就被挂到等待队列中睡眠。当条件得到满足时,该任务就被移出等待队列,此时并不意味着该任务就被马上执行,因为它又被移进工作队列中等待CPU资源,在适当的时机被调度。

内核信号量是在内部使用等待队列的,也就是说该等待队列对用户是隐藏的,无须用户干涉。由用户真正使用的等待队列我们将在另外的篇章进行详解。

四、内核信号量的相关函数

1、初始化

(1)、该宏声明一个信号量name是直接将结构体中count值设置成n,此时信号量可用于实现进程间的互斥量。

#define __SEMAPHORE_INITIALIZER(name, n)                               
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值