目录
一.背景和意义
在实际编程中,我们会经常碰到这种场景:进程P需要等待条件C的成立,才能继续执行某个动作。例如,当串口没有数据可以读取时,我们可以通过轮询的方式,等到有数据来的时候,串口程序再去读取。但是这种方式显得比较笨拙,影响CPU的性能。因此,内核中提供了等待队列的方式,即可以将进程P先挂到等待队列Q(wait_queue)上去,并将进程的状态由RUNNING切换为睡眠状态,主动让出CPU,直到条件满足时,由内核调用wake_up()接口,自动唤醒Q上的所有进程,这样进程P就继续执行。
因此,wait_queue的实现,能够提高整个系统以及CPU运行的效率。
二.数据结构分析
wait_queue使用到的数据结构很简单,就是使用内核链表,将等待同一事件的所有进程串联起来。
第一个数据结构是等待队列头:
struct wait_queue_head {
spinlock_t lock; \\用于同步的自旋锁
struct list_head head; \\等待队列头
};
typedef struct wait_queue_head wait_queue_head_t;
等待队列头可以用以下API进行初始化:
wait_queue_head_t wait_queue_head;
init_waitqueue_head(&wait_queue_head);
第二个数据结构是等待队列的队列元素:
struct wait_queue_entry {
unsigned int flags; //1代表互斥进程,0代表非互斥进程
void *private; //一般用于指向当前进程,即设置为current指针
wait_queue_func_t func; //唤醒方式
struct list_head entry; //用于链表管理
};
这里,睡眠进程被分成两种,flags为1代表的是互斥进程,这些进程