并发与竞态——信号量与互斥体

Release log:

2021-04-27 二: 完成初版

原文地址

说明

前一段时间学习了《LINUX 设备驱动程序》中的“并发与竞态”章节,没过多久在阅读代码时,看到了 spin_lock_bh 这个函数,然后一脸瞢逼,这个函数后缀有啥意义来着?所以决定对这一章节做一个简单整理,一是为了加深印象,二是为了后续的快速回顾以及查找

资源共享的规则

  1. 只要可能,就应该避免资源的共享。如果我们将资源放在多个线程都会找到的地方,则必须有足够的理由
  2. 在单个执行线程之外共享硬件或软件资源的任何时候,因为另外一个线程可能产生对该资源的不一致观察,因此必须显式地管理对该资源的访问
  3. 当内核代码创建了一个可能和其他内核部分共享的对象时,该对象必须在还有其他组件引用自己时保持存在(并正确工作)

信号量和互斥体

在计算机科学中,信号量是一个众所周知的概念。一个信号量本质上是一个整数值,它和一对函数联合使用,这一对函数通常称为 P 和 V。希望进入临界区的进程将在相关信号量上调用 P;如果信号量的值大于零,则该值减小一,而进程可以继续。相反,如果信号量的值为零(或更小),进程必须等待直到其他人释放该信号量。对信号量的解锁通常调用 V 完成;该函数增加信号量的值,并在必要时唤醒等待的进程

当信号量用于互斥时(即避免多个进程同时在一个临界区中运行),信号量的值应初始化为 1

Linux 内核中信号量的使用

在 Linux 内核中,要使用信号量需要包含头文件 <linux/semaphore.h>,相关的类型为 struct semaphore

信号量的声明以及初始化函数

DECLARE_MUTEX(name);
void sema_init(struct semaphore *sem, int val);
void init_MUTEX(struct semaphore *sem);

Linux 中,P 函数被称为 down,下面是他的几个版本:

void down(struct semaphore *sem); // 非可中断操作,用于建立不可杀进程(ps 输出中的 "D state")
int down_interruptible(struct semaphore *sem); // 可中断,被中断时返回非零值,调用者未拥有该信号量
int down_killable(struct semaphore *sem); // 可以被 fatal signal 打断
int down_trylock(struct semaphore *sem); // 不会休眠,如果信号量在调用时不可获取,立即返回非零值
int down_timeout(struct semaphore *sem, long timeout); // timeout 是以 jiffies 计数

Linux 中,等价与 V 的函数是 up

void up(struct semaphore *sem);

读取者/写入者信号量

读取者/写入者信号量被称为 rwsem,使用时需要包含 <linux/rwsem.h>,相关的数据类型为 struct rw_semaphore

rwsem 的初始化函数如下

void init_rwsem(struct rw_semaphore *sem);

rwsem 用于只读访问的操作如下

void down_read(struct rw_semaphore *sem); // 可能将进程至于不可中断的休眠中
int down_read_trylock(struct rw_semaphore *sem); // 成功返回 1,否则返回 0
void up_read(struct rw_semaphore *sem);

rwsem 用于写入者的操作如下

void down_write(struct rw_semaphore *sem);
int down_write_trylock(struct rw_semaphore *sem);
void up_write(struct rw_semaphore *sem);
void downgrade_write(struct rw_semaphore *sem); // 将写入者降级为读取者

写入者具有更高优先级,如果大量写入者竞争一个信号量,这种实现会导致读取者“饿死”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值