一.IO模型
IO模型有阻塞IO,非阻塞IO,信号驱动IO,IO多路复用,异步IO。其中前四个被称之为同步IO。
1.阻塞IO模型
IO阻塞模型是一种传统的输入/输出处理方式,在这种模型中,当进程发起一个IO操作(如读取文件或网络通信)时,如果数据尚未准备好,进程会阻塞(即暂停执行)直到数据就绪,在此期间,进程不执行任何其他操作。
等待队列是Linux内核用来实现阻塞和唤醒的一种机制,它以循环链表为基础结构。在Linux系统中,等待队列头由一个特定的结构体表示,这个结构体定义了一个自旋锁和一个链表头。通过这些元素,等待队列能够有效地管理任务的状态转换,确保系统资源的合理分配和使用。等待队列头使用结构体wait_queue_head_t来表示,该结构体包括一个自旋锁(spinlock_t lock)和一个链表头(struct list_head task_list)。这种设计使得等待队列能够在并发环境下安全地操作,同时允许任务挂起或恢复执行。
struct _wait_queue_head {
spinlock_t lock; // 自旋锁
struct list_head task_list; // 链表头
};
typedef struct _wait_queue_head wait_queue_head_t;
结构体wait_queue_t表示等待队列项,结构体内容如下:
struct __wait_queue {
unsigned int flags; // 标志位
void *private; // 私有指针
wait_queue_func_t func; // 函数指针
struct list_head task_list; // 任务列表头
};
typedef struct __wait_queue wait_queue_t;
初始化等待队列头
分步定义和初始化:
- 定义:首先声明一个等待队列头的变量,例如 wait_queue_head_t test_wq;。
- 初始化:然后使用 init_waitqueue_head 函数来初始化这个等待队列头,例如 init_waitqueue_head(&test_wq);。
宏定义和初始化:
- 使用 DECLARE_WAIT_QUEUE_HEAD 宏来同时完成等待队列头的定义和初始化,例如 DECLARE_WAIT_QUEUE_HEAD(test_wq);。
这两种方法都用于创建一个等待队列头,这是Linux内核中用于线程或进程等待某些事件发生的一种机制。等待队列头是管理这些等待操作的基础结构。
创建等待队列项
创建等待队列项的宏定义:DECLARE_WAITQUEUE(name, tsk)
参数:
- name:等待队列项的名字。
- task:表示这个等待队列项属于哪个任务(进程),一般设置为current。
解释:
DECLARE_WAITQUEUE(wait, current); // 创建一个名为wait的等待队列项
add_wait_queue(wq, &wait); // 将wait这个等待队列项加到wq这个等待队列当中
等待事件相关的函数:
1. wait_event(wq, condition)
- 功能: 让调用进程进入不可中断的睡眠状态,直到 condition 变为真,被内核唤醒。
- 参数:
- wq: 类型为 wait_queue_head_t 的变量,代表等待队列头。
- condition: 等待的条件。只有当 condition 为假时,进程才会进入睡眠;如果 condition 为真,则不会进入睡眠。
2. wait_event_interruptible(wq, condition)
- 功能: 让调用进程进入可中断的睡眠状态,直到 condition 变为真被内核唤醒或收到信号中断。
- 参数:
- wq: 类型为 wait_queue_head_t 的变量,代表等待队列头。
- condition: 等待的条件。只有当 condition 为假时,进程才会进入睡眠;如果 condition 为真,则不会进入睡眠。
这两个函数的主要区别在于 wait_event_interruptible() 允许进程在中断发生时被唤醒,而 wait_event() 则不允许。
唤醒事件相关函数:
1.wake_up(wait_queue_head_t *q)
- 功能:唤醒所有休眠的进程。
2.wake_up_interruptible(wait_queue_head_t *q)
- 功能:唤醒可以被中断的休眠进程。
通过这两个函数,可以有效地管理进程的状态转换,确保系统资源的高效利用和设备的正常操作。
如何使用等待队列?
- 初始化等待队列列表,并将条件设置成假(condition=0)。
- 指出在需要阻塞的地方调用wait_event(),使进程进入休眠状态。
- 当条件满足时,需要解除休眠,先将条件置为真(condition=1),然后调用wake_up函数唤醒等待队列中的休眠进程
#include <linux/wait.h