poll这个单词的意思是轮询,轮流询问。当一个应用程序可以访问多个设备,可以从多个设备中获取或者写入数据,但是有时候设备不一定准备好了,所以就有一个询问设备是否准备好的过程,内核提供了poll系统调用来查询这些设备是否可读或是可写,这依赖于驱动的poll实现。
应用层的poll
- #include <poll.h>
- int poll(struct pollfd fds[], nfds_t nfds, int timeout);
- struct pollfd {
- int fd;
- short events;
- short revents;
- };
fds是文件集,nfds是文件个数,timeout是超时时间,以ms为单位。
返回可用文件的个数,如果为0表示超时了。
events设置要等待的条件,revents返回的条件:
POLLIN|POLLRDNORM 标志一个可读的设备
POLLOUT|POLLWRNORM 标志一个可写的设备
POLLHUP 文件尾部
使用poll比较简单,只要设置好fds,然后poll一次,检测events,然后进行相关处理就OK了。
驱动层的poll
当应用程序调用poll时,驱动层的poll会被调用,驱动层poll的主要工作:
1. 在一个或多个可指示查询状态变化的等待队列上调用 poll_wait.
2. 返回一个位掩码, 描述可能不必阻塞就立刻进行的操作.
linux/fs.h
- unsigned int (*poll) (struct file *filp, struct poll_table_struct *poll_table);
- linux/poll.h
- void poll_wait (struct file *filp, wait_queue_head_t *wq, poll_table *pt);
poll_wait的作用是增加调用poll应用程序的进程到等待队列,这样当事件到达(IO空间可读或可写的时候)就会唤醒应用程序。
给内存设备驱动增加poll:
- unsigned int base_char_poll(struct file*filp,struct poll_table_struct *poll_table)
- {
- struct dev_info_struct *dev_info_ptr=(struct dev_info_struct*)filp->private_data;
- unsigned int mask=0; poll_wait(filp,&dev_info_ptr->wq,poll_table);
- mask |= POLLOUT|POLLWRNORM;//always can write
- if(dev_info_ptr->have_data!=0) mask |= POLLIN|POLLRDNORM; printk("base char: poll :\n");
- return mask;
- }
测试:test.c
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <linux/poll.h>
- int main()
- {
- int fd=open("/dev/base_char",O_RDWR);
- int count=0;
- if(fd<0)
- {
- perror("");
- return -1;
- }
- char buf[50];
- struct pollfd fds[1];
- int ret=0;
- fds[0].fd=fd;
- fds[0].events=POLLIN | POLLRDNORM;
- ret=poll(fds,1,10*1000);
- if(ret>0 && (fds[0].revents & POLLIN) && (fds[0].revents & POLLRDNORM))
- {
- printf("start to read..\n");
- read(fd,buf,50);
- printf("read data: %s\n",buf);
- }
- if(ret==0)
- {
- printf("wait timeout!\n");
- }
- close(fd);
- return 0;
- }
阅读(1899) | 评论(0) | 转发(0) |