`init_completion` 是 Linux 内核API中用于初始化一个完成变量(completion variable)的宏。完成变量是Linux内核中用于同步的一种机制,它允许一个任务(进程或线程)等待直到一个或多个事件发生。当这些事件完成时,等待这些事件的任务会被唤醒。完成变量常用于内核中的异步操作完成通知、资源初始化完成信号等场景。
1 定义与用法
`init_completion` 宏的定义位于 `<linux/completion.h>` 头文件中。它的基本形式如下:
```c
#define init_completion(x) \
do { \
(x)->done = 0; \
init_waitqueue_head(&(x)->wait); \
} while (0)
```
这个宏接受一个指向`struct completion`结构体的指针作为参数,主要完成两件事:
1. **初始化完成计数器**:将结构体内的`done`字段设置为0,表示没有任何事件完成。
2. **初始化等待队列头**:通过`init_waitqueue_head`初始化与该完成变量关联的等待队列头,等待队列头用于挂载那些正在等待事件完成的进程。
### struct completion 结构
`struct completion` 结构定义如下:
```c
struct completion {
unsigned int done;
wait_queue_head_t wait;
};
```
- `unsigned int done`: 记录完成的事件数量,初始化时为0,当事件完成时,通过`complete`或`complete_all`增加这个计数。
- `wait_queue_head_t wait`: 是一个等待队列头,用于挂载等待该事件完成的所有进程的等待队列项。
2 使用场景
`init_completion` 通常与以下两个函数配合使用:
1. **`complete(&completion_var)`**:当一个事件完成时,调用此函数将`done`计数加1,并唤醒一个或所有等待在该完成变量上的进程。
2. **`wait_for_completion(&completion_var)`**:使调用者睡眠,直到`completion_var`的`done`字段变为非0,即至少有一个`complete`调用发生。这对于同步非常有用,特别是在驱动程序中,当需要等待某个操作(如DMA传输完成)结束时。
3 实际应用
例如,在驱动程序中,当发起一个异步操作(如发送一个网络包或启动硬件操作)后,可以初始化一个完成变量,然后在操作完成时调用`complete`,而主线程或其他需要等待该操作完成的代码则调用`wait_for_completion`等待。
```c
struct completion my_comp;
...
init_completion(&my_comp);
/* 发起异步操作 */
start_async_operation();
/* 等待操作完成 */
wait_for_completion(&my_comp);
/* 这里代码继续执行,表示操作已完成 */
```
通过这种方式,`init_completion`及相关的完成变量机制为内核提供了灵活且高效的同步手段。