poll接口《来自Linux驱动程序开发实例》

您所在的位置:读书频道 > 操作系统 > Linux > 1.2.7 poll接口

1.2.7 poll接口

2012-05-22 13:38 冯国进 机械工业出版社 我要评论(0) 字号: T | T
一键收藏,随时查看,分享好友!

《Linux驱动程序开发实例》第1章 Linux设备驱动程序模型,本章主要介绍Linux内核中的驱动程序模型,包括三类设备的驱动程序、proc文件系统、Sysfs文件系统、Kobject等内容。本节为大家介绍poll接口。

AD: 51CTO云计算架构师峰会 抢票进行中!


    1.2.7  poll接口

    如果设备被配置成阻塞式操作,即当设备执行I/O操作时如果不能获得数据将阻塞,直到获得数据。应用层可以使用select函数查询设备当前的状态,以便用户程序获知是否能对设备进行非阻塞的访问。使用select函数需要在设备驱动程序中添加file_operations->poll接口支持。一个典型的字符驱动程序的file_operations->poll函数的实现如下:

       
       
    1. static unsigned int my_poll(struct file *file, struct poll_table_struct *wait)  
    2. {  
    3.     unsigned int mask = 0;  
    4.     poll_wait(file, & outq, wait);//把当前进程添加到等待列表  
    5.     if (0 != bta->read_count)//如果有数据  
    6.         mask |= (POLLIN | POLLRDNORM);  
    7.     return mask;  
    8. }  

    驱动程序中的poll函数返回的标志如下:
       
       
    1. #define POLLIN            1 //设备可以无阻塞地读取  
    2. #define POLLPRI       2//可以无阻塞地读取高优先级数据(带外数据)  
    3. #define POLLOUT       4//设备可以无阻塞地写入  
    4. #define POLLERR       8//设备发生错误  
    5. #define POLLHUP       16//当读取设备的进程到达文件尾部  
    6. #define POLLNVAL          32 //请求无效  
    7. #define POLLRDNORM    64//常规数据已经就绪  
    8. #define POLLWRNORM  POLLOUT  
    9. #define POLLRDBAND    128//可以从设备读带外数据  
    10. #define POLLWRBAND    256//可以向设备写带外数据  
    11. #define POLLMSG       0x0400  
    12. #define POLLREMOVE   0x1000  
    13. #define POLLRDHUP    0x2000  

    应用层多路I/O选择函数select的原型如下:
       
       
    1. 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时间后若没有文件描述符准备好则返回。文件描述符集常用函数接口如下:

    FD_ZERO(fd_set *set)//清除一个文件描述符集;

    FD_SET(int fd,fd_set *set)//将文件描述符fd加入文件描述符集中;

    FD_CLR(int fd,fd_set *set)//将文件描述符fd从文件描述符集中清除;

    FD_ISSET(int fd,fd_set *set)//判断文件描述符fd是否被置位。

    例1.7  poll接口驱动程序示例

    代码见光盘\src\1drivermodel\1-7poll。核心代码如下所示:

       
       
    1. FD_ZERO(fd_set *set)//清除一个文件描述符集;   
    2. FD_SET(int fd,fd_set *set)//将文件描述符fd加入文件描述符集中;   
    3. FD_CLR(int fd,fd_set *set)//将文件描述符fd从文件描述符集中清除;   
    4. FD_ISSET(int fd,fd_set *set)//判断文件描述符fd是否被置位。  

    例1.7  poll接口驱动程序示例

    代码见光盘\src\1drivermodel\1-7poll。核心代码如下所示:

       
       
    1. ssize_t simple_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)  
    2. {  
    3.     //printk("wait_event_interruptible before\n");  
    4.     wait_event_interruptible(read_queue, simple_flag);  
    5.     //printk("wait_event_interruptible after\n");  
    6.     if (copy_to_user(buf,demoBuffer,count))  
    7.     {  
    8.         count=-EFAULT;  
    9.     }  
    10.     return count;  
    11. }  
    12. ssize_t simple_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)  
    13. {  
    14.     if (copy_from_user(demoBuffer, buf, count))  
    15.     {  
    16.         count = -EFAULT;  
    17.         goto out;  
    18.     }  
    19.     simple_flag=1;  
    20.     wake_up(&read_queue);  
    21. out:  
    22.     return count;  
    23. }  
    24. //poll接口实现  
    25. unsigned int simple_poll(struct file * file, poll_table * pt)  
    26. {  
    27.     unsigned int mask = POLLIN | POLLRDNORM;  
    28.     poll_wait(file, &read_queue, pt);  
    29.     return mask;  
    30. }  
    31. struct file_operations simple_fops = {  
    32.     .owner =    THIS_MODULE,  
    33.     .poll =     simple_poll,  
    34.     .read =     simple_read,  
    35.     .write=     simple_write,  
    36.     .open =     simple_open,  
    37.     .release =  simple_release,  
    38. };  

    应用程序参考代码如下:
       
       
    1. int fd;  
    2. void *readthread(void *arg)//读数据线程  
    3. {  
    4.     char data[256];  
    5.     fd_set rfds; //读描述符集合  
    6.     fd_set wfds; //写描述符集合  
    7.     int retval=0;  
    8.     while(1)  
    9.     {  
    10.         FD_ZERO(&rfds);  
    11.          FD_SET(fd, &rfds);  
    12.         select(fd+1, &rfds, &wfds, NULL, NULL); //多路选择  
    13.         if(FD_ISSET(fd, &rfds))  
    14.         {  
    15.             retval=read(fd,data,3);  
    16.             if(retval==-1)  
    17.             {  
    18.                 perror("read error\n");  
    19.                 exit(-1);  
    20.             }  
    21.             data[retval]=0;  
    22.             printf("read successfully:%s\n",data);  
    23.         }  
    24.     }  
    25.     return (void *)0;  
    26. }   
    27. void main()  
    28. {  
    29.     int i;  
    30.     int retval;  
    31.     fd=open("/dev/fgj",O_RDWR);  
    32.     if(fd==-1)  
    33.     {  
    34.         perror("error open\n");  
    35.         exit(-1);  
    36.     }  
    37.     printf("open /dev/fgj successfully\n");  
    38.     pthread_t tid;  
    39.     pthread_create(&tid, NULL, readthread, NULL);//创建读线程  
    40.     while(1)  
    41.     {  
    42.         retval=write(fd,"fgj",3);//主线程负责写数据  
    43.         if(retval==-1)  
    44.         {  
    45.             perror("write error\n");  
    46.             exit(-1);  
    47.         }  
    48.     }  
    49.     close(fd);  
    50. }  

    本例运行结果如下:
       
       
    1. [root@urbetter /home]# insmod demo.ko  
    2. [root@urbetter /home]# mknod /dev/fgj c 224 0  
    3. [root@urbetter /home]# ./test  
    4. read successfully:fgj  
    5. read successfully:fgj  
    6. read successfully:fgj  
    7. read successfully:fgj  
    8. ...  

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

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值