您的位置:首页 > 运维架构 > Linux

4.阻塞和非阻塞

2016-04-18 11:41 465 查看
一.概念

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 内核