在linux内核中,引入锁机制主要是解决资源并发与竞争问题;
主要常用锁机制:信号量,自旋锁,互斥锁;
线程间的 同步大多使用completion信号量,而互斥资源的保护大多使用自旋锁和互斥锁。.
该篇文章主要讲解的是completion完成量。也算是信号量中的一种。
completion信号量是一个轻量级的机制,它允许一个线程告诉另一个线程某个工作已经做完了。
一般信号量的的处理会限制在一个函数内,但是有时候函数A的处理的前提条件是函数B,
A必须等待B处理后才能继续,可以用信号量来进行处理,但linux kernel提供complete的方式。使用方式如下文所示:
(1) init
(2) wait_for_completion A在这个位置上等待B的执行
(3) complete_all B执行完,A就可以执行,无论多少次
以下代码分析是在kernel4.14下
1 completion结构体
struct completion {
unsigned int done;
wait_queue_head_t wait;
};
字段解释:
(1) unsigned int done;
等待的事件是否完成。初始化时为0,表示等待的事件未完成;大于0,表示等待的事件已经完成。
(2) wait_queue_head_t wait;
存放等待该事件完成的进程队列
2 定义和初始化
struct completion my_completion;
init_completion(&my_completion);
define init_completion(x) __init_completion(x)
static inline void __init_completion(struct completion *x)
{
x->done = 0;
init_waitqueue_head(&x->wait);
}
直接定义并调用init_completion()初始化。init_completion()会将done字段初始化为0,wait字段的自旋锁为未锁,等待队列为空。这说明调用该完成量的进程必须等待某事件完成(即另外一进程必须先调用completiom()唤醒该完成量)。
3 等待完成量的释放
wait_for_completion_timeout(&my_completion, 10);
这个函数的返回值如果>0,<10,说明等到了一个反馈,即是my_completion通过complete_all这个函数释放掉了
unsigned