并发控制

Posted IT利刃出鞘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发控制相关的知识,希望对你有一定的参考价值。

目录

自旋锁

完成量


自旋锁

 

《Linux设备驱动开发详解》=> 7.5 自旋锁

spinlock:在rt linux(配置了PREEMPT_RT)的时候可能会被抢占
                (实际底层可能是使用支持PI(优先级翻转)的mutex)。
raw_spinlock:即便是配置了PREEMPT_RT也要顽强的spin

头文件位置:
include/linux/spinlock_types.h
include/linux/spinlock.h

spinlock中的定义

raw_spinlock的定义

接口API的含义

DEFINE_SPINLOCK(x)

DEFINE_RAW_SPINLOCK(x)

定义spin lock并初始化

spin_lock_init(lock)

raw_spin_lock_init(lock)

动态初始化spin lock

spin_lock(lock)

raw_spin_lock(lock)

获取指定的spin lock

spin_lock_irq(lock)

raw_spin_lock_irq(lock)

获取指定的spin lock同时disable本CPU中断

spin_lock_irqsave(lock)

raw_spin_lock_irqsave(lock)

保存本CPU当前的irq状态,disable本CPU中断并获取指定的spin lock

spin_lock_bh(lock)

raw_spin_lock_bh(lock)

获取指定的spin lock同时disable本CPU的bottom half(中断后半部)

spin_trylock(lock)

raw_spin_trylock(lock)

如果能立即获得锁,它获得锁并返回真;否则立即返回假,
不会自旋等待lock被释放。

spin_trylock_irq(lock)

raw_spin_trylock_irq(lock)

如果获得自旋锁lock,它将保存标志寄存器的值到变量flags中,并且失效本地中断,如果没有获得锁,它什么也不做。

spin_trylock_irq(lock)

raw_spin_trylock_irq(lock)

类似于spin_trylock_irqsave,只是该宏不保存标志寄存器

spin_trylock_bh(lock)

raw_spin_trylock_bh(lock)

如果获得了自旋锁,它失效本地软中断。如果得不到锁,
它什么也不做。

spin_is_locked(lock)

raw_spin_is_locked(lock)

判断spin lock是否是locked,如果其他的thread已经获取了该lock,
那么返回非零值,否则返回0

spin_can_lock(lock)

raw_spin_is_locked(lock)

判断自旋锁lock是否能够被锁,它实际是spin_is_locked取反。如果lock没有被锁,它返回真,否则,返回假

spin_unlock(lock)

raw_spin_unlock(lock)

释放指定的spin lock

spin_unlock_irq(lock)

raw_spin_unock_irq(lock)

释放指定的spin lock同时enable本CPU中断

spin_unlock_irqstore(lock)

raw_spin_unlock_irqstore(lock)

释放指定的spin lock同时恢复本CPU的中断状态

spin_unlock_bh(lock)

raw_spin_unlock_bh(lock)

获取指定的spin lock同时enable本CPU的bottom half

spin_trylock(lock)

raw_spin_trylock(lock)

尝试去获取spin lock,如果失败,不会spin,而是返回非零值

完成量

        用于一个执行单元等待另一个执行单元完成某事。
        完成量(completion)是Linux系统提供的一种比信号量更好的同步机制,是对信号量的一种补充。使用完成量等待时,调用进程是以独占睡眠方式进行等待的,不是忙等待。
        函数定义在头文件linux/completion.h中。

定义完成量

struct completion my_completion;

 

初始化完成量

init_completion(&my_completion);

需要先定义,才能用此函数。

DECLARE_COMPLETION(my_completion);

定义并初始化完成量。之前不用先定义。

等待完成量

void wait_for_completion

      (struct completion* comp)

该函数等待一个完成量被唤醒;该函数会阻塞调用进程,如果所等待的完成量没有被唤醒,那就一直阻塞下去,而且不会被信号打断;

int wait_for_completion_interruptible

      (struct completion* comp):

该函数等待一个完成量被唤醒;但是它可以被外部信号打断;

 

int wait_for_completion_killable

      (struct completion* comp):

该函数等待一个完成量被唤醒;但是它可以被kill信号打断;

 

unsigned long wait_for_completion_timeout

     (struct completion* comp,

      unsigned long timeout):

 

该函数等待一个完成量被唤醒;该函数会阻塞调用进程,如果所等待的完成量没有被唤醒,调用进程也不会一直阻塞下去,而是等待一个指定的超时时间timeout,当超时时间到达时,如果所等待的完成量仍然没有被唤醒,那就返回;超时时间timeout以系统的时钟滴答次数jiffies计算;

bool try_wait_for_completion

     (struct completion* comp):

该函数尝试等待一个完成量被唤醒;不管所等待的完成量是否被唤醒,该函数都会立即返回;

bool completion_done

       (struct completion* comp):

检查是否有执行单元阻塞在完成量comp上(是否已经完成)。
返回0:表示有执行单元被完成量comp阻塞。相当于wait_for_completion_timeout()中的timeout=0。

注意:

这几个函数都会把进程添加到等待队列中,进程在等待队列中以独占睡眠方式进行等待,直到请求被内核中的某些部分处理;

唤醒完成量

void complete (struct completion* comp):

该函数只唤醒一个正在等待完成量comp的执行单元;

void complete_all(struct completion* comp):

该函数唤醒所有正在等待同一个完成量comp的执行单元;

NORET_TYPE void complete_and_exit

     (struct completion* comp, long code):

该函数唤醒一个正在等待完成量comp的执行单元,并退出,code为退出码;

 

注意

在内核处理完请求之后,必须调用这三个函数中的一个,来唤醒其它正在等待的进程;

 

以上是关于并发控制的主要内容,如果未能解决你的问题,请参考以下文章

并发控制

为啥数据库系统要采用并发控制?

mysql的并发控制

Elasticsearch系统学习-ES并发控制

MySQL: InnoDB的并发控制,锁,事务模型

python多线程并发数量控制