并发控制&互斥锁

    xiaoxiao2022-07-06  207

    并发控制的解决办法是保证对共享资源的互斥访问,所谓的互斥访问是指一个执行单元在访问共享资源的时候,其他的执行单元被禁止访问。

    访问共享资源的代码区域称为临界区,临界区需要被以某种互斥机制加以保护。

    互斥机制:

    中断屏蔽  原子操作  自旋锁  信号量  互斥体都是Linux设备驱动中采用的互斥途径

     

    中断屏蔽

    只能解决本CPU,无法解决SMP多CPU引发的竞态

     

    原子操作

    定义原子变量: static atomic_t xxx_available() = ATOMIC_INIT(1);

    atomic_inc

    atomic_dec

     

    自旋锁

    主要针对SMP或单CPU但内核可抢占的情况

    Spin Lock:原地打转

    how to use:

    定义自旋锁 spinlock_t lock;

    初始化自旋锁 spin_lock_init(&lock);

    获得自旋锁  spin_lock(&lock)   spin_trylock(&lock)

    ...//临界区

    释放自旋锁  spin_unlock(&lock)

     

    1.只有在占用锁时间短的情况下使用才合理

    2.可能导致死锁 

    3.在自旋锁锁定期间不能调用可能引起进程调度的函数 copy_from_user() msleep() kmalloc()等,否则可能导致内核崩溃

     

    此外还有,读写锁rwlock ,顺序锁 seqlock,读-复制-更新(RCU read-copy-update)

     

     

    信号量

    Semaphore

    定义信号量 struct semaphore sem;

    初始化信号量 void sema_init(struct semaphore *sem,int val)

    获得信号量 void down(struct semaphore *sem)    down_interruptible()    down_trylock()

    释放信号量 void up(struct semaphore *sem)

    与自旋锁不同的是,当获取不到信号量时,进程不会原地打转,而是进入休眠等待状态

     

     

    互斥体

    mutex

    定义并初始化互斥体 struct mutex crazy_mutex;   mutex_init(&crazy_mutex)

    获得互斥体 void  mutex_lock(struct mutex* lock)  

                        int mutex_lock_interruptible(struct mutex *lock)

                        int mutex_trylock(struct mutex *lock)

    释放互斥体  void  mutex_unlock(struct mutex *lock)

     

    1.当锁不能被获取时,使用互斥体的开销是进程上下文切换的时间,而自旋锁的开销是等待获取自旋锁。若临界区比较小,可使用自旋锁,若临界区很大,则使用互斥体。

    2.互斥体所保护的临界区可包含可能引起阻塞的代码,而自旋锁则绝对要避免用来保护这样代码的临界区。因为阻塞意味着要进行进程的切换,如果进程被切换出去后,另一个进程企图获取本自旋锁,死锁就会发生。

    3.互斥体存在于进程上下文,因此,如果被保护的共享资源需要在中断或软中断情况下使用,则应选择自旋锁。

     

    完成量

    定义完成量 struct completion com;

    初始化完成量 init_completion(&com);

     等待完成量  void wait_for_completion(struct completion *c)

    唤醒完成量  void complete(struct completion *c)    void complete_all(struct completion *c)  

    最新回复(0)