1. 程式人生 > >linux裝置驅動中的阻塞和非阻塞IO

linux裝置驅動中的阻塞和非阻塞IO

一、等待佇列
1、定義等待佇列頭
wait_queue_head_t my_queue;
2、初始化等待佇列頭
init_waitqueue_head(&my_queue);
3、定義等待佇列
DECLARE_WAITQUEUE(name,tsk);
4、新增/移除等待佇列
void fatcall add_wait_queue(wait_queue_head_t *q,wait_queue_t *wait);
void fatcall remove_wait_queue(wait_queue_head_t *q,wait_queue_t *wait);
5、等待事件
wait_event(queue,condition);
wait_event_inturruptible(queue,condition);
wait_event_timeout(queue,condition,timeout);
wait_event_inturruptible_timeout(queue,condition,timeout);
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);
8、等待佇列的使用
tatic ssize_t xxx_write(struct file *file,const char *buffer,ssize_t count,loff_t *ppos)
{
....
DECLARE_WAITQUEUE(wait,current);//定義等待佇列
add_wait_queue(&xxx_wait,&wait);//新增等待佇列

ret=count;
//等待裝置緩衝區可寫
do{
avail=device_writable();
if(avail<0)
__set_curent_stats(TASK_INTERRUPTIBLE);//改變程序狀態TASK_INTERRUPTIBLE

if(avail<0){
if(file->f_flags & O_NONBLOCK){//非阻塞
if(!ret)
ret=-EAGAIN;
goto out;
}
schedule();//排程其他程序
if(signal_pending(current)){
if(!ret)
ret=-ERESTARTSYS;
goto out;
}
}
}while(avail<0);

//寫裝置緩衝區
device_write()
out:
remove_wait_queue(&xxx_wait,&wait);//移除等待佇列
set_current_state(TASK_RUNNING);//設定程序狀態為TASK_RUNNING
}


二、輪詢操作
1、應用程式中的輪詢程式設計
int select(int numfd,fd_et *readfd,fd_set *writefds,fd_set *execptfds,struct timeval *timeout);
readfd:讀檔案描述符集合
writefds:寫檔案描述符集合
execptfds:異常處理檔案描述符集合
2、檔案描述符的操作
FD_ZERO(fd_set *set);//清楚一個檔案描述符集合
FD_SET(int fd,fd_set *set);//將一個檔案描述符加入到檔案描述符集合中
FD_CLR(int fd,fd_set *set);//將一個檔案描述符從檔案描述符集合中移除
FD_ISSET(int fd,fd_set *set);//判斷檔案描述符是否置位


2、裝置驅動中的輪詢程式設計
unsigned int (*poll)(struct file *filp,struct poll_table *wait);
3、poll函式的模板
unsigned int (*poll)(struct file *filp,struct poll_table *wait)
{
unsigned int mask=0;
struct xxx_dev *dev=filp->private_data;//獲得裝置結構體指標
....
poll_wait(filp,&dev->r_wait,wait);//加入讀等待佇列
poll_wait(filp,&dev->w_wait,wait);//加入寫等待佇列

if(...)//可讀
mask|=POLLIN | POLLRDNORM;

if(...)//可寫
mask|=POLLIN | POLLWDNORM;

return mask;
}