同步与互斥

并发的概念在linux系统中十分常见,系统中的并发发生在如下情况中:

1.中断.

2.进程调度抢占.

3.多处理器下的多进程并发,也是严格意义上的并发.

并发的存在带来的了不可避免的问题->资源竞争,所以linux内核中实现了多种互斥机制来解决这个问题.

在单核不可抢占系统中,使用local_irq_enable和local_irq_disable关闭中断是防止并发带来问题的有效方式.单核不可抢占系统现在很少见了,所以不再讨论范围之内.

  • 自旋锁

自旋锁的设计思路和线程同步思想有相似之处,都是通过设置标志位表示对资源的占有,清除标志位表示对资源的释放.这样在多处理器之间达到同步的目的.当然,这一思想的关键之处在于对标志位的操作保持原子性.

关闭调度器是因为在一个内核态的执行路径在某些情况下会被中断,在这个调度点上,如果一个更高级的进程到来并且执行,可能会破坏共享资源的保护.

真正的操作在do_raw_spin_lock中实现(鉴于是用汇编实现的,所以这里简单介绍一下实现了什么功能).do_raw_spin_lock实现如下功能:

  1. 读取自旋锁状态
  2. 判断标志位是否为0,如果不为0则进入自旋上锁状态.
  3. 判断标志是否为0,如果是0,则更新标志位为1.并把更新执行的结果放入tmp中.
  4. 判断3的更新结果是否为0,若是0代表更新成功,进入临界区.否则进入忙等状态.

对应的,释放锁的函数spin_unlock实现如下:

Spin_lock也有许多变体函数,这里大概介绍一下:

  1. spin_lock_irq()与spin_lock不同的是,这个方法关闭了本地处理器的外部中断的处理.也就是执行路径进入临界区后不会被中断挂起.
  2. spin_lock_bh()与spin_lock不同的是关闭了软中断的处理.
  3. spin_try_lock的实现是非阻塞版本的spin_lock,在申请锁时如果发现锁被占有会直接返回0,成功会返回1.
  • rwlock:

读写锁允许任意进程同时读,但是写入者受互斥访问限制.也就是说,

  1. 当一个进程正在写,那么别的进程就不能写也不能读.
  2. 如果一个进程正在读,那么别的进程可以读但不能写.

  • 信号量

与自旋锁不同的是,信号量的调用进程在操作信号量时如果发现信号量已经被占用,那么会进入休眠队列而不是忙等状态.

Down操作:

如上函数的功能可以通过命名猜出在功能上的细微差别.下边是等待队列的模型:

下面介绍一下信号量的原理,如下:

 

在等待队列中的进程会被如下原因唤醒:

  1. 持有信号量的进程up操作完成.
  2. 进程睡眠超时被唤醒.
  3. 进程被异常唤醒.

Up操作:

 

RW信号量:

在普通信号量的基础上实现的RW信号量,意图等同于rwlock.这里不再赘述.

  • RCU

RCU是LINUX中的一种免锁互斥访问机制.这一机制的使用比较少(最新版本的kernel中mptcp部分看到过).

简单来说,RCU是通过一个共享指针p来存放数据.供写入者和读取者操作.但是写入者的操作消耗很大,所以在确认写入操作远远小于读取操作的情况下建议使用RCU机制.

对RCU的读操作,首先构建临界区,操作指针,退出临界区.此外,在临界区内不可以存在睡眠操作,退出临界区后也不可以操作指针.

对RCU的写操作为重新分配一个保护区,替换之前RCU中的p指针.在保证老指针不被饮用后,释放老指针.释放指针的操作需要在调用函数call_rcu中注册的回调函数void func(struct rcu_head *rcu)中释放.

  • 完成接口

完成接口被用来协调多个执行路径的执行顺序.这里需要说明一下等待队列的原理.

等待队列:

等待队列是一个双向链表,用来存放等待进程的结点.并且等待队列也有自己的自旋锁,用来方式并发操作下带来的问题.

等待队列的结点构成中,flag为唤醒操作的行为模式,private为只想当前进程的指针,func为唤醒操作函数,task_list为将各个结点串联起来的链表.

完成接口:

完成接口可以用等待着,等待部分模型表示.

对于完成者的行为,可以使用complete和completion_all完成(看着是不是很想java多线程中的wait,notify/notifyAll方法呢)

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值