Linux驱动程序:POLL机制
POLL机制的引入
以我们上一节 按键中断驱动程序为例,整个简易流程图如下:
可以看到程序在进入read函数以后,如果没有读到键值,就会一直让进程休眠,等待按键中断唤醒。
如果我们在这个基础上引入POLL机制,就可以达到下面的效果:
由上面的流程图可以看到,我们引入POLL机制以后,倘若没有按键按下,那么超过多少时间之后,进程能够继续得到执行,而不是没有按键按下,就永远休眠。
相关函数
poll()函数
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
-
输入参数
- fds 可以传递多个结构体,也就是说可以监测多个驱动设备所产生的事件,只要有一个产生了请求事件,就能立即返回
- nfds 监测驱动文件的个数
- timeout 超时时间,单位为ms
输入参数中的 pollfd 结构体如下
struct pollfd {
int fd; /* 文件描述符 */
short events; /* 请求的事件类型,监视驱动文件的事件掩码 */
short revents; /* 驱动文件实际返回的事件 */
} ;
事件类型events 可以为下列值:
POLLIN 有数据可读
POLLRDNORM 有普通数据可读,等效与POLLIN
POLLPRI 有紧迫数据可读
POLLOUT 写数据不会导致阻塞
POLLER 指定的文件描述符发生错误
POLLHUP 指定的文件描述符挂起事件
POLLNVAL 无效的请求,打不开指定的文件描述符
测试
实验平台
内核版本:Linux-4.19.5
开发板:SAMSUNG JZ2440
实验程序
/* 驱动程序 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
int major; //主设备号
static struct class *buttons_class;
volatile unsigned long *gpfcon;
volatile unsigned long *gpfdat;
volatile unsigned long *gpgcon;
volatile unsigned long *gpgdat;
/* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 */
/* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */
static unsigned char key_val; //返回给用户的键值
static DECLARE_WAIT_QUEUE_HEAD(button_waitq); //休眠队列
static volatile int ev_press = 0; //条件变量
const int t_s3c2440_devid[4] = {
1, 2, 3, 4}; //键值数组
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
int i_pinselect = *((int *)dev_id);
int i_pinval = 0;
unsigned long ul_regval;