Linux设备驱动程序第三版学习(7)- 高级字符驱动程序操作(续2)- poll/select .

 第六章:高级字符驱动程序操作(续2)
以下为第三部分:poll/select系统调用

poll方法执行了两个任务:
第一项任务:调用poll_wait方法向poll_table结构添加一个等待队列
第二项任务:返回一个位掩码(mask),该位掩码秒数了哪个操作可以立即执行而不会被阻塞。

对于位掩码,定义在asm-generic/poll.h中,为了以后方便查阅,记录如下:
  
  1. /* These are specified by iBCS2 */  
  2. #define POLLIN        0x0001    //如果设备可以无阻塞的读取,就设置该位   
  3. #define POLLPRI        0x0002    //设置该位可以无阻塞地读取高优先级的数据   
  4. #define POLLOUT        0x0004    //如果设备可以无阻塞地写入,就设置该位   
  5. #define POLLERR        0x0008    //设备发生了错误   
  6. #define POLLHUP        0x0010    //当读取进程到达文件尾时,则必须设置该位挂起   
  7. #define POLLNVAL    0x0020       
  8.   
  9. /* The rest seem to be more-or-less nonstandard. Check them! */  
  10. #define POLLRDNORM    0x0040    //如果“通常”的数据已经就绪,可以读取,就设置该位   
  11. #define POLLRDBAND    0x0080    //这一位指示可以从设备读取频带之外(out of band)的数据   
  12. #ifndef POLLWRNORM   
  13. #define POLLWRNORM    0x0100    //该位和POLLOUT的意义一样   
  14. #endif   
  15. #ifndef POLLWRBAND   
  16. #define POLLWRBAND    0x0200    //与POLLRDBAND类似,这一位表示具有非零优先级的数据可以被写入设备   
  17. #endif   
  18. #ifndef POLLMSG   
  19. #define POLLMSG        0x0400   
  20. #endif   
  21. #ifndef POLLREMOVE   
  22. #define POLLREMOVE    0x1000   
  23. #endif   
  24. #ifndef POLLRDHUP   
  25. #define POLLRDHUP       0x2000   
  26. #endif  
 
看一下scullpipe中的poll实现:
  1. static unsigned int scull_p_poll(struct file *filp, poll_table *wait)  
  2. {  
  3.     struct scull_pipe *dev = filp->private_data;  
  4.     unsigned int mask = 0;  
  5.   
  6.     /* 
  7.      * The buffer is circular; it is considered full 
  8.      * if "wp" is right behind "rp" and empty if the 
  9.      * two are equal. 
  10.      */  
  11.     down(&dev->sem); //加锁   
  12.     //下面是poll的第一项任务   
  13.     poll_wait(filp, &dev->inq,  wait);  
  14.     poll_wait(filp, &dev->outq, wait);  
  15.   
  16.     //下面是poll的第二项任务   
  17.     if (dev->rp != dev->wp)  
  18.         mask |= POLLIN | POLLRDNORM;    /* readable */  
  19.     if (spacefree(dev))  
  20.         mask |= POLLOUT | POLLWRNORM;    /* writable */  
  21.     up(&dev->sem); //解锁   
  22.     return mask; //返回位掩码   
  23. }  


===============================================================================================
总结:当应用程序调用poll或select时就会知道接下来要进行的操作是否会阻塞。
通常将poll和read/write一起使用,综合分析前面的read和write方法可以知道从设备读取数据和向设备写入数据的流程。
从设备读取数据:
*如果输入缓冲区有数据,那么及时就绪的数据比程序所请求的少,并且驱动程序保证剩下的数据马上就能到达,read调用仍然应该以难以察觉的延迟立即返回。read甚至可以一直返回比所请求数目少的数据(至少返回一个字节)。
*如果输入缓冲区没有数据,那么默认情况read必须阻塞等待,直到至少一个字节到达。而如果设置了O_NONBLOCK标志,则read不阻塞,应立即返回,返回值是-EAGAIN。这时poll必须报告设备不可读,直到至少一个字节到达。一旦缓冲区有了数据,就回到了上一种情况
*如果已经到达文件为,则read应该立即返回0,无论是否阻塞。此时poll应该报告POLLHUP(挂起)

向设备写数据:
*如果输出缓冲区有空间,则write应该无延迟地立即返回。它可以接收比请求少的数据(知道接收一个字节)。这时poll报告设备可写。
*如果输出缓冲区已满,那么默认情况write被阻塞直到有空间。如果设置了O_NONBLOCK标志,则write不阻塞,应立即返回,返回值是-EAGAIN。这时poll报告文件不可写。另一方面,如果设备不能再接收任何数据,则write返回-ENOSPC(no space left on device 设备无可用空间),而不管是否阻塞。
*永远不要让write在返回前等待数据的传输结束,即使O_NONBLOCK被清除。因为应用程序用select来检查write是否会阻塞,如果poll报告设备可以写入,则write就不会被阻塞。驱动程序可以实现fsync方法来保证输出缓冲区的数据确实已经被传送出去了。

===============================================================================================

 

原文出处:http://blog.csdn.net/ypoflyer/article/details/6131324

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值