驱动程序学习(五)select and poll

来源:互联网 发布:淘宝买抱枕 编辑:程序博客网 时间:2024/05/21 04:26

Select()系统调用

在驱动程序中一个进程同时处理多个文件描述符是很常见的情况。select()系统调用可以使进程检测同时等待的多个I/O设备,当没有设备准备好时,select()阻塞,其中任一设备准备好时,select()就返回。

select()的调用形式为:
#include <sys/select.h>
#include <sys/time.h>

int select(int maxfd, fd_set *readfds, fd_set *writefds, fe_set *exceptfds, const struct timeval *timeout);
select的第一个参数是文件描述符集中要被检测的比特数,这个值必须至少比待检测的最大文件描述符大1;
参数readfds指定了被读监控的文件描述符集;
参数writefds指定了被写监控的文件描述符集;
而参数exceptfds指定了被例外条件监控的文件描述符集。
参数timeout起了定时器的作用:到了指定的时间,无论是否有设备准备好,都返回调用。timeval的结构定义如下:
struct timeval{
long tv_sec; //表示几秒
long tv_usec; //表示几微妙
}

timeout取不同的值,该调用就表现不同的性质:
1.timeout为0,调用立即返回;
2.timeout为NULL,select()调用就阻塞,直到知道有文件描述符就绪;
3.timeout为正整数,就是一般的定时器。

select调用返回时,除了那些已经就绪的描述符外,select将清除readfds、writefds和exceptfds中的所有没有就绪的描述符。select的返回值有如下情况:
1.正常情况下返回就绪的文件描述符个数;
2.经过了timeout时长后仍无设备准备好,返回值为0;
3.如果select被某个信号中断,它将返回‐1并设置errno为EINTR。
4.如果出错,返回‐1并设置相应的errno。

当用户调用select系统调用时,select系统调用会先调用poll_initwait(&table);,然后调用驱动程序中 struct file_operations下的fop->poll函数,在这个函数里应该调用poll_wait(),将current加到某个等待队列(这里调用poll_wait()),并检查是否有效,如果无效就调用schedule_timeout();去睡眠。事件发生后,schedule_timeout()回来,,调用fop->poll();,检查到可以运行,就调用poll_freewait(&table);从而完成select系统调用。重要的是fop->poll()里面要检查是否就绪,如果是,要返回相应标志。

Poll()系统调用

Linux中的字符设备驱动中有一个函数

unsigned int (*poll)(struct file * fp, struct poll_table_struct * table)
此函数在系统调用select内部被使用,作用是把当前的文件指针挂到设备内部定义的等待
队列中。这里的参数table可以不考虑,是在select函数实现过程中的一个内部变量。
函数具体实现时:
wait_queue_head_t t = ((struct mydev *)filp->private_data)->wait_queue;
poll_wait(filp, t, table);
return mask;
这里mask可以是:
POLLIN | POLLRDNORM
POLLOUT | POLLWRNORM
这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,下面是这个函数的声明:
#include <poll.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
参数说明:

fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符

nfds:nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量;
  
timeout:是poll函数调用阻塞的时间,单位:毫秒

返回值:
  >0:数组fds中准备好读、写或出错状态的那些socket描述符的总数量;
       ==0:数组fds中没有任何socket描述符准备好读、写,或出错;此时poll超时,超时时间是timeout毫秒;换句话说,如果所检测的socket描述符上没有任何事件发生的话,那么poll()函数会阻塞timeout所指定的毫秒时间长度之后返回,如果timeout==0,那么poll() 函数立即返回而不阻塞,如果timeout==INFTIM,那么poll() 函数会一直阻塞下去,直到所检测的socket描述符上的感兴趣的事件发生是才返回,如果感兴趣的事件永远不发生,那么poll()就会永远阻塞下去;
      -1: poll函数调用失败,同时会自动设置全局变量errno;
   
看完上面这些定义和介绍,我们做个实验来验证下。
根据select的定义,在调用他后
调用驱动程序中 struct file_operations下的fop->poll函数
我们修改的基础是驱动程序学习(四)并发控制(3)阻塞和非阻塞里的驱动源码
http://blog.csdn.net/zhaole20094463/article/details/7906750
所以首先我们要在驱动程序中定义poll函数。

首先修改file_operations
在该结构体里添加
.poll = chardev.poll

然后添加处理函数
static  ssize_t int chardev_poll(struct *filp,poll_table *wait )
{
unsigned int mask = 0;
poll_wait(filp,&outq,wait);

if(flag !=0)
{
mask |= POLLIN | POLLRDNORM;
}
return mask;
}

然后编写我们的测试程序
chardevtest_select.c

#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>


main()
{
int fd,num;
fd_set rfds;
struct timeval tv;

fd = open("/dev/chardev",O_RDWR,S_IRUSR | S_IWUSR);
if(fd != -1)
{
while(1)
{
/*查看chardev是否有输入*/
FD_ZERO(&rfds);
FD_SET(fd,&rfds);
/*设置超时时间为5s*/
tv.tv_sec = 5;
tv.tv_usec = 0;
select(fd+1,&rfds,NULL,NULL,&tv);

if(FD_ISSET(fd,&rfds))
{
read(fd,&num,sizeof(int));
printf("The chardev is %d\n",num);


  if(num == 0)
{
close(fd);
break;
}
}
else
printf("NO data within 5 seconds.\n");
}
}
else
printf("Open file failure.\n");
}
首先来介绍一下该文件中用到的API
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)判断文件描述符是否被置位了。
通过这几个函数的讲解我们就能看明白测试程序了
FD_ZERO(&rfds);先清楚文件描述符集
FD_SET(fd,&rfds);然后将我们要检测的文件描述符添加到文件描述符集里。
接着设置时间,然后监听。
所以这个函数的实际效果就是5s内没有输入则打印信息
NO data within 5 seconds.



原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机淘宝退货物流单号填错了怎么办 买家要求退货退款但是不发货怎么办 多给买家寄包裹不接电话怎么办 给买家发货物流单号错了怎么办 淘宝退货退款快递单号填错了怎么办 淘宝不小心点了延迟收货怎么办 淘宝快递地址错了货已经发了怎么办 卖家送运费险买家填错单号怎么办 买家无赖点了延迟收货卖家怎么办 淘宝卖家快递单号填错了怎么办 淘宝店有当天的快递忘记发货怎么办 在美国官网买东西少寄了东西怎么办 闲鱼退货货收了不退钱怎么办 闲鱼退货卖家收到东西不退钱怎么办 淘宝店铺物流服务给差评怎么办 在合肥东方融资网被骗了怎么办 微信今年绑定频繁明年再试怎么办 手机号码注销了微信密码忘了怎么办 摄像师把婚礼资料弄丢了怎么办 青岛拍的婚纱照修的不好怎么办 鞋店剩的鞋都是小码的怎么办 淘宝想买的衣服下架了怎么办 买家要求到付仲裁发生运费怎么办 淘宝退货退款页面刷新不出来怎么办 淘宝退货退款快递单号写错了怎么办 淘宝上已经退款的店家还发货怎么办 千牛买家下单付款了卖家怎么办 京东货到付款支付宝支付退款怎么办 美萍餐饮管理系统下单错误怎么办 淘宝店上传宝贝显示空间不足怎么办 淘宝店品牌被投诉未授权怎么办 淘宝天猫退货单号填错了怎么办 淘宝退货我把快递单号弄丢了怎么办 唯品会退货快递单号填错了怎么办 天猫换货写错运单号怎么办 训练衣舍的店铺名连接怎么办 兼职模特被骗去微整还贷了款怎么办 卖家已经发货了我要退款怎么办 卖家显示发货单号信息查不到怎么办 淘宝申请退款卖家发货了怎么办 咸鱼卖家不发货好会自动退款怎么办