Linux内核互斥锁的实现方式

文章详细介绍了Linux内核中互斥锁的实现,包括自旋锁和睡眠锁的差异。自旋锁是一种忙等策略,当锁被占用时,会持续检查直至获得锁。互斥锁则在无法获取时,线程会进入睡眠状态。文章深入探讨了互斥锁的数据结构、加锁和解锁的函数接口,以及阻塞和唤醒的具体实现过程,展示了如何使用自旋锁保护等待队列并管理锁的状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自旋锁

自旋锁是一个忙等锁,如果获取不到锁就会一直等待。
如下为忙等锁的实现方式,使用了一个原子变量(原子操作的实现和硬件有关)来实现:

#include <atomic>

class SpinLock {
   
private:
    std::atomic_flag flag;

public:
    SpinLock() : flag(ATOMIC_FLAG_INIT) {
   }

    void lock() {
   
        while (flag.test_and_set(std::memory_order_acquire)) {
   
            // 自旋等待锁释放
        }
    }

    void unlock() {
   
        flag.clear(std::memory_order_release);
    }
};

互斥锁

互斥锁是一个睡眠锁,获取不到则线程就会睡眠引起任务调度,互斥锁可以使用信号量实现也可以用自旋锁来实现,下面将会对用自旋锁实现互斥量的方式展开讲。

1.互斥锁的数据结构

struct mutex {
   
   atomic_t  count; //引用计数器,1: 所可以利用,小于等于0:该锁已被获取,需要等待
   spinlock_t  wait_lock;//自旋锁类型,保证多cpu下,对等待队列访问是安全的。
   struct list_head wait_list; //等待队列,如果该锁被获取,任务将挂在此队列上,等待调度。
};

如上所示,互斥锁的数据结构主要有三个变量构成:

  • count:用来记录目前锁的状态 1: 所可以利用,小于等于0:该锁已被获取,需要等待。
  • wait_lock:自旋锁,操作等待队列的时候会使用自旋锁将等待队列保护起来。
  • wait_list:因为获取不到这个锁而阻塞的进程。

2.加锁函数接口

void inline __sched mutex_lock(struct mutex *lock)

实际上是调用了一个宏:

__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);

宏的定义:将mutex数据结构中,引用计数器减1,如果不为负数就返回,如果为负数,需要调用函数:__mutex_lock_slowpath,接下来我们再来分析这个函数,我们先来分析一下这个宏。

#define __mutex_fastpath_lock(count, fail_fn)  
do {
           
   unsigned int dummy;/    
   ; 检查参数类型的有效性
   typecheck(atomic_t *, count);  /  
   typecheck_fn(void (*)(atomic_t *), fail_fn
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值