• Linux内核互斥技术1


    Linux内核互斥技术

    在内核中,可能出现多个进程访问同一个对象、进程和硬中断访问同一个对象、多个处理器访问同一个对象等现象,我们需要使用互斥技术,确保每个时刻只有一个主体可以进入临界区访问对象

    如果临界区的执行时间比较长或者可能睡眠,可使用:

    1. 信号量,大多数我们使用互斥信号量
    2. 读写信号量
    3. 互斥锁
    4. 实施互斥锁
      申请这些锁的时候,如果锁被其他进程占有,进程将会睡眠等待,代价很高

    如果申请临界区的执行时间短,并且不会睡眠,那么使用上面的锁不太合适,因为进程切换代价很高,可以使用:

    1. 原子变量
    2. 自旋锁
    3. 读写自旋锁
    4. 顺序锁
      申请这些锁的时候,如果锁被其他进程占有,进程自旋等待(也称忙等待)

    进程还可以使用以下技术

    1. 禁止内核抢占,防止被当前处理器上的其他进程抢占
    2. 禁止软中断,防止被当前处理器上的软中断抢占
    3. 禁止硬中断,防止被当前处理器上的硬中断抢占

    避免使用锁的互斥技术

    1. 每处理器变量
    2. 每处理器计数器
    3. 内存屏障
    4. 读-复制更新
    5. 可睡眠RCU

    信号量

    信号量允许多个进程同时进入临界区,大多情况下只允许一个进程进入临界区,把信号量的计数值设置为1,即二值信号量,也称为互斥信号量
    与自旋锁相比,信号量适合保护比较长的临界区,因为竞争信号量时进程可能睡眠被再次唤醒,代价高

    struct semaphore {
    	raw_spinlock_t		lock; /* 自旋锁,保护信号量其他成员 */
    	unsigned int		count; /* 计数器,表示还可以允许多少进程进入临界区 */
    	struct list_head	wait_list; /* 等待进入临界区的进程链表 */
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    读写信号量

    struct rw_semaphore {
    	atomic_long_t count;
    	atomic_long_t owner;
    #ifdef CONFIG_RWSEM_SPIN_ON_OWNER
    	struct optimistic_spin_queue osq; /* spinner MCS lock */
    #endif
    	raw_spinlock_t wait_lock; /* 自旋锁,保护信号量其他成员 */
    	struct list_head wait_list; /* 等待进入临界区的进程链表 */
    #ifdef CONFIG_DEBUG_RWSEMS
    	void *magic;
    #endif
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
    	struct lockdep_map	dep_map;
    #endif
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    互斥锁

    互斥锁只允许一个进程进入临界区,适合保护比较长的临界区,因为竞争互斥锁时进程可能睡眠和再次唤醒,代价很高,尽管可以把二值信号量当作互斥锁使用

    struct mutex {
    	atomic_long_t		owner;
    	spinlock_t		wait_lock;
    #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
    	struct optimistic_spin_queue osq; /* Spinner MCS lock */
    #endif
    	struct list_head	wait_list;
    #ifdef CONFIG_DEBUG_MUTEXES
    	void			*magic;
    #endif
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
    	struct lockdep_map	dep_map;
    #endif
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    实时互斥锁

    如果使用实时互斥锁,编译内核时需要开启配置宏CONFIG_RT_MUTEXES

    struct rt_mutex {
    	raw_spinlock_t		wait_lock;
    	struct rb_root_cached   waiters;
    	struct task_struct	*owner;
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
    	struct lockdep_map	dep_map;
    #endif
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    原子变量

    自旋锁

    读写自旋锁

    顺序锁

    禁止内核抢占

    进程和软中断互斥

    进程和硬中断互斥

    每处理器变量

    每处理器计数器

    内存屏障

    RCU

    可睡眠RCU

    死锁检测工具

  • 相关阅读:
    gRPC:以 C++为例
    github代码比对颜色介绍
    详解Git合并(Merge)错误如何回退。(包括Reset, Revert和页面回滚三种,并说明其优缺点)
    简记C语言清空输入残留内容
    C++笔记
    springmvc复习(第二天)(黑马版)
    设计模式入门
    外包干了2个月,技术退步明显...
    【机器学习】用 EM 算法推导解释 Kmeans?(面试回答)
    网络基础(2)
  • 原文地址:https://blog.csdn.net/wangxiandou/article/details/126681493