驱动基石之poll机制

poll机制的引入

通常我们阻塞读取按键值时,是这样操作的:

在驱动程序里创建中断,按下按键时,上升沿和下降沿会触发中断,在drv_read里阻塞程序,直到有按键按下时,才读取。

但是这种做法一直阻塞,让后面的程序都无法运行了,现在引入poll机制,当阻塞超过定时时间时,就退出阻塞。

使用poll机制的话,驱动程序要这样写:

让drv_open线程挂起,直到有按键按下,或则超时时才从内核态返回到应用态。

应用层要这样写:

struct pollfd fds[1];
int timeout_ms = 5000;
int ret;
fds[0].fd = fd;
fds[0].events = POLLIN;
ret = poll(fds, 1, timeout_ms);
if ((ret == 1) && (fds[0].revents & POLLIN))
{
read(fd, &val, 4);
printf(“get button : 0x%x\n”, val);
}

调用poll的简单流程

驱动基石之poll机制_第1张图片
首先应用调用poll函数,在poll函数里调用内核文件系统的sys_poll函数,在sys_poll函数里会调用驱动层的drv_poll函数。
drv_poll函数如下:
驱动基石之poll机制_第2张图片
首先poll_wait函数会将当前线程挂入队列 wq(为了中断服务函数能找的到,以便唤醒),但是并不是在 drv_poll 中进入休眠,而
是在调用 drv_poll 之后休眠,它会先执行完一边drv_poll,因为没有按键按下,所以返回的值为0,且没有超时。所以当前线程进入休眠,直到有按键按下,按键的中断函数会唤醒这个线程,或则当定时时间超时时候也会退出。
驱动基石之poll机制_第3张图片

所以驱动层里的drv_poll实际上会被使用两次,这是因为,第一次drv_poll把当前线程挂入队列 wq,期间没有按键按下,也没有超时,线程进入休眠,当按键按下发生中断,唤醒线程或则定时时间超时的时候都会再执行以此drv_poll。

你可能感兴趣的:(linux)