首页 > 代码库 > linux驱动编写之poll机制

linux驱动编写之poll机制

一、概念

1、poll情景描述

      以按键驱动为例进行说明,用阻塞的方式打开按键驱动文件/dev/buttons,应用程序使用read()函数来读取按键的键值。这样做的效果是:如果有按键按下了,调用该read()函数的进程,就成功读取到数据,应用程序得到继续执行;倘若没有按键按下,则要一直处于休眠状态,等待这有按键按下这样的事件发生。

      这种功能在一些场合是适用的,但是并不能满足我们所有的需要,有时我们需要一个时间节点。倘若没有按键按下,那么超过多少时间之后,也要返回超时错误信息,进程能够继续得到执行,而不是没有按键按下,就永远休眠。这种例子其实还有很多,比方说两人相亲,男方等待女方给个确定相处的信,男方不可能因为女方不给信,就永远等待下去,双方需要一个时间节点。这个时间节点,就是说超过这个时间之后,不能再等了,程序还要继续运行,需要采取其他的行动来解决问题。

example:  

      单片机编程,等待IIC设备一个事件的发生,如果在允许的时间内发生了就返回1(SUCCESS),否则返回0(ERROR)。

uint8_t I2C_WaitForEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT,int32_t delay)
{    

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT) && (delay-- > 0));
    
    if(delay < 0){
        return 0;
    }
    
    return 1;
}

      此段函数代码可以这样来调用,如下:

int8_t I2C_EE_PageWrite(u8* pBuffer, u16 WriteAddr, u8 NumByteToWrite)
{
      .............
      if(I2C_WaitForEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED, 100000) != 1){
            return -1;
      }
      ............
}

      这个例子是STM32单片机写i2cflash--AT24C02,可见上述的页写函数调用的等待字节传输完成函数(I2C_EVENT_MASTER_BYTE_TRANSMITTED)

,如果在限定的时间内(CPU将100000减到0),还没有成功写入,那么就将返回超时错误,页写函数也会返回写入失败的错误信息。之后,任务重新得到了运行。

      对于单片机这样通常单任务运行的状况,必须采取这样的措施。如果没有超时限制,那么程序将陷入死机,不能再继续运行。

2、linux应用程序poll的使用

     对于类似的场景,linux系统使用poll功能来解决这样的问题。而且,与上述单片机等待方式不同,linux系统再调用poll()函数时候,如果没有发生需要的事件,那么进程进入休眠。如果在限定的时间内得到需要的事件,那么成功返回,如果没有则返回超时错误信息。

     可见,等待期间将进程休眠,利用事件驱动来唤醒进程,将更能提高CPU的效率。下面,以一个应用例程来说明poll的应用程序使用方法:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <poll.h>

int main(int argc, char **argv)
{
    int i;
    int ret;
    int fd;
    unsigned char keys_val;
    struct pollfd fds[1];
    
    fd = open("/dev/buttons", 0);  // 打开设备
    if (fd < 0) {
        printf("Can‘t open /dev/buttons\n");
        return -1;
    }

    fds[0].fd = fd;
    fds[0].events = POLLIN;
    
    while (1) {
        ret = poll(fds,1, 5000);
        if(ret == 0)
        {
            printf("time out!\n");
        }
        else
        {
            read(fd, &keys_val, sizeof(keys_val));
            printf("keys_val = 0x%x\n",keys_val);
        }
    }
    
    close(fd);
    return 0;    
}

 

linux驱动编写之poll机制