4.阻塞和非阻塞

一.概念
1.IO阻塞:驱动中通过实现poll。
2.等待队列头相当于一个双向链表的头,等待队列相当于双向列表中的链表项
3.等待队列由循环链表实现,其元素包括指向进程描述符的指针。每个等待队列都有一个等待队列头(wait queue head)
4.当一个任务需要在某个wait_queue_head上睡眠时,将自己的进程控制块信息封装到wait_queue中,然后挂载到wait_queue的链表中,执行调度睡眠。当某些事件发生后,
另一个任务(进程)会唤醒wait_queue_head上的某个或者所有任务,唤醒工作也就是将等待队列中的任务设置为可调度的状态,并且从队列中删除。

二.常见问题
1.当用户程序调用read函数时,驱动程序的read并没有准备好数据或write的缓冲区已满,怎么办?
用户程序不会管理这些问题。驱动程序默认情况下,阻塞该进程。将其置入休眠状态直到请求可继续.
直接返回,这是非阻塞IO
2.如何将进程安全的进入休眠状态?
不能在原子上下文进行休眠,休眠时,对外界一无所知,进程必须重新检测等待条件,进程只有确保会被其他进程唤醒,才能进入休眠。
3.等待队列的作用
实现阻塞进程的唤醒。
实现内核中的异步事件通知机制:队列的数据结构,系统的调度机制
同步系统资源的访问:Semaphore可以用wait queue来实现

三.驱动模块功能相关的结构体
1.Struct __wait_queue_head_t(wait_queue_head_t):等待队列头
  __wait_queue_t(wait_queue_t):等待队列
struct __wait_queue_head {
  spinlock_t  lock;          //自旋锁变量,用于在对等待队列头          
  struct list_head task_list;  // 指向等待队列的list_head
}; 
Struct wait_queue_head_t作用:实现休眠和唤醒功能,用于中断处理、进程同步、定时等场合
成员函数:#include <linux/wait.h>
初始化:
a.静态
DECLARE_WAIT_QUEUE_HEAD(name);//定义并初始化等待队列头
DECLARE_WAITQUEUE(name,tsk)  //定义并初始化等待队列,tsk = current;
b.动态
wait_queue_head_t xxx_queue;
init_waitqueue_head(&xxx_queue);
功能函数:向等待队列中添加或移除等待队列。实现休眠和唤醒功能
a.添加/移除等待队列
void fastcall add_wait_queue(wait_queue_head_t *q,wait_queue_t *wait);
void fastcall remove_wait_queue(wait_queue_head_t *q,wait_queue_t *wait);
b.等待事件
wait_event(queue,condition);
wait_event_interruptible(queue,condition);
wait_event_timeout(queue,condition,timeout);
wait_event_interruptible_timeout(queue, condition,timeout);
c.唤醒事件
wake_up(wait_queue_head_t *queue);
wake_up_interruptible(wait_queue_head_t *queue);
wake_up_all(wait_queue_head_t *queue);
wake_up_interruptible_all(wait_queue_head_t *queue);
wake_up_nr(wait_queue_head_t *queue,int nr);
wake_up_interruptible_nr(wait_queue_head_t *queue,int nr);
wake_up_interruptible_sync(wait_queue_head_t *queue);
d.等待队列睡眠
sleep_on(wait_queue_head_t *p);//将目前进程状态设置成TASK_UNINTERRUPTIBLE,并定义一个等待队列,之后把他添加到等待队列头q,然后睡眠直到资源可获取
(wake_up()),q引导的等待队列被唤醒。
interruptible_sleep_on(wait_queue_head_t *p);
释放资源:
void fastcall remove_wait_queue(wait_queue_head_t *q,wait_queue_t *wait);

四.其他内核函数
static inline void init_waitqueue_entry(wait_queue_t *q,struct task_struct *p)//#include <linux/wait.h>用于在本文件中初始化等待队列
#define __set_current_state(state_value)//#include <linux/sched.h>,设置进程状态为TASK_UNINTERRUPTIBLE,则改变进程状态为睡眠
amslinkage void __sched schedule(void);//EXPORT_SYMBOL(schedule),调度其他进程。
signed long __sched schedule_timeout(signed long timeout)//EXPORT_SYMBOL(schedule_timeout),进程切换


你可能感兴趣的:(linux,内核)