阻塞是指执行设备操作时,不能获得 资源,则挂起进程直到满足可操作的条件在进行操作。
非阻塞是在进程不能进行设备操作时,并不挂起,要么放弃、要么不停的查询,直到进行操作为止。
等待队列;
typedef struct _wait_queue_head wait_queue_head_t;
1.定义等待队列头部:wait_queue_head_t my_head;
2.初始化等待队列头:init_waitqueue_head(&my_queue);
DECLARE_WAIT_QUEUE_HEAD(name)可以作为 定义并初始化等待队列头的“快捷方式”。
3.定义等待队列元素:
DECLARE_WAITQUEUE(name,tsk);
4,添加和移除等待队列
void add_wait_queue(wait_queue_head_t *q, wiat_queue_t *wait);
void remove_wait_queue(wait_queue_head_t *q, wiat_queue_t *wait);
add_wait_queue()用于将等待队列元素wait添加到等待队列的头部q指向的双向链表中,
void remove_wait_queue用于将等待队列元素wait从等待队列的头部q指向的双向链表移除。
5.等待事件
wait_event(queue,condition)
wait_event_interruptible(queue,condition);
等待参数queue作为等待队列头部的队列被唤醒,condition必须满足,否则继续阻塞。
6.唤醒队列
void wake_up(wait_queue_head_t *queue);
void wake_up_interruptible(wait_queue_head_t *queue);
要对应起来用。
7,在等待队列上的睡眠
sleep_on(wait_queue_head_t *queue);
interruptible_sleep_on(wait_queue_head_t *queue);
sleep_on()函数的作用将进程状态置成task_uninterruptible,定义一个等待队列元素。之后把它赋予到q指向的队列,直到资源获得。
interruptible_sleep_on()函数的作用将进程状态置成task_interruptible。
Linux进程状态
1.如果非阻塞访问(o_nonblock)设备忙时,直接返回“-EAGAIN”
2.对于阻塞访问,会调用_set_current_state(task_interruptible)进行进程的状态切换并显示通过"schedule()"调度其他进程的执行
3.醒来的时候注意,由于调度出去的时候,进程状态task_interruptible,即浅度睡眠,唤醒的可能是信号,通过signal_pending(current)了解是不是信号,是返回“erestartsys”
轮询
int select(int numfd,fd_set *readfds, fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
其中readfds ,writefds,expectfds分别是select()监视的读写和异常处理 的文件描述符集合。
poll函数原型
unsigned int (*poll)(struct file * filp, struct poll_table* wait);
1.对可能引起设备文件变化状态的等待队列调用poll_wait(),将对应的等待队列头部添加到poll_table
2.返回表示是否对设备进行无阻塞读,写访问的掩码。
void poll_wait(struct file *filp,wait_queue_head_t *queue,poll_table *wait)
poll_wait就是把当前进程添加到wait参数指定的等待列表,实际让唤醒参数queue对应的等待队列可以唤醒因select()而睡眠的进程。