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),进程切换
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 socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程