莫小帅|Linux kernel同步机制(上篇)( 三 )


可以发现 , 信号量是基于spinlock实现的 , 对其封装以满足高级的功能 , 例如全局共享资源的配置 , 并通过等待队列较为灵活的调度 。 信号量与接下来要讲的mutex都建立在自旋锁实现的执行同步上 。
了解了信号量的结构与定义 , 我们来看看最核心的两个实现down, up 。
down & up
莫小帅|Linux kernel同步机制(上篇)
down用于调用者获得信号量 , 若count大于0 , 说明资源可用 , 将其减一即可 。
莫小帅|Linux kernel同步机制(上篇)
若count<0,将task加入等待队列 , 并进入等待队列 , 并进入调度循环等待 , 直至其被__up唤醒 , 或者因超时以被移除等待队列 。
莫小帅|Linux kernel同步机制(上篇)
up用于调用者释放信号量 , 若waitlist为空 , 说明无等待任务 , count+1 , 该信号量可用 。
莫小帅|Linux kernel同步机制(上篇)
若waitlist非空 , 将task从等待队列移除 , 并唤醒该task,对应__down条件 。
Semaphore API
莫小帅|Linux kernel同步机制(上篇)
四、互斥锁(Mutex)Linux 内核互斥锁是非常常用的同步机制 , 互斥锁是这样一种同步机制:在互斥锁中同时只能有一个任务可以访问该锁保护的共享资源 , 且释放锁和获得锁的调用方必须一致 。 因此在互斥锁中 , 除了对锁本身进行同步 , 对调用方(或称持有者)必须也进行同步 。 当互斥锁无法获得时 , task会加入等待队列 , 直至可获得锁为止 。
Structure Definition
莫小帅|Linux kernel同步机制(上篇)
互斥锁从结构上看与信号量十分类似 , 但将原本的int类型的count计数 , 改成了atomic_long_t的owner以便同步 , 保证释放者与持有者一致 。
mutex_lock & mutex_unlock
莫小帅|Linux kernel同步机制(上篇)
莫小帅|Linux kernel同步机制(上篇)
上图简单的表现了mutex_lock与mutex_unlock实现的对称性 , ___mutex_trylock_fast用于owner为0的特殊状态 , 用于快速加锁 , 实现核心在slowpath版本上 。
*might_sleep指在之后的代码执行中可能会sleep 。
由于mutex实现的具体步骤相当复杂 , 这里选讲比较核心简单的两块 。 Mutex有关等待队列的处理比较复杂 , 有兴趣阅读相关内核书籍 。
莫小帅|Linux kernel同步机制(上篇)当且仅当lock当前的owner没有变化时(没有其他mutex抢先拥有该锁) , 此时获得锁 , 返回NULL, owner 为 curr | flags,owner本身对应task指针 。 若该锁已被占用 , owner和当前task不匹配 , 返回owner对应指针 。


推荐阅读