Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->Linux程序设计 ->正文

Linux设备驱动编程之阻塞与非阻塞

来源: 作者: 时间:2007-04-11 点击: [收藏] [投稿]

即交换wait_event_interruptible(outq, flag != 0)和down_interruptible(&sem)的顺序,这个驱动程序把变得不可运行。实际上,当两个可能要阻塞的事件同时出现时,即两个wait_event或down摆在一起的时候,把变得非常危险,死锁的可能性很大,这个时候我们要特别留意它们的出现顺序。当然,我们应该尽可能地避免这种情况的发生!

还有一个与设备阻塞与非阻塞访问息息相关的论题,即select和poll,select和poll的本质一样,前者在BSD Unix中引入,后者在System V中引入。poll和select用于查询设备的状态,以便用户程序获知是否能对设备进行非阻塞的访问,它们都需要设备驱动程序中的poll函数支持。

驱动程序中poll函数中最主要用到的一个API是poll_wait,其原型如下:

void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table * wait);

poll_wait函数所做的工作是把当前进程添加到wait参数指定的等待列表(poll_table)中。下面我们给globalvar的驱动添加一个poll函数:

static unsigned int globalvar_poll(struct file *filp, poll_table *wait)
{
 unsigned int mask = 0;

 poll_wait(filp, &outq, wait);

 //数据是否可获得? 
 if (flag != 0)
 {
  mask |= POLLIN | POLLRDNORM; //标示数据可获得
 }
 return mask;
}

需要说明的是,poll_wait函数并不阻塞,程序中poll_wait(filp, &outq, wait)这句话的意思并不是说一直等待outq信号量可获得,真正的阻塞动作是上层的select/poll函数中完成的。select/poll会在一个循环中对每个需要监听的设备调用它们自己的poll支持函数以使得当前进程被加入各个设备的等待列表。若当前没有任何被监听的设备就绪,则内核进行调度(调用schedule)让出cpu进入阻塞状态,schedule返回时把再次循环检测是否有操作可以进行,如此反复;否则,若有任意一个设备就绪,select/poll都立即返回。

我们编写一个用户态应用程序来测试改写后的驱动。程序中要用到BSD Unix中引入的select函数,其原型为:

int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文件描述符集合,numfds的值是需要检查的号码最高的文件描述符加1。timeout参数是一个指向struct timeval类型的指针,它可以使select()在等待timeout时间后若没有文件描述符准备好则返回。struct timeval数据结构为:

struct timeval 
{ 
  int tv_sec; /* seconds */ 
  int tv_usec; /* microseconds */ 
};


 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:Linux编程之序列化存储Python对象(下)   下一篇:Linux操作系统套接字编程的5个隐患

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号