设备驱动基础学习--poll

使用非阻塞I/O的应用程序通常会使用select()和poll()系统调用查询是否可对设备进行无阻塞的访问,这两个系统调用最终又会引发设备驱动中的poll()函数被执行,所以我们的问题就集中到了如何编写设备驱动中的poll()函数就可以了。先来看看设备驱动中的poll()函数原型:

unsigned int (*poll)(struct file *filp, struct poll_table *wait);

这个函数要进行下面两项工作。首先,对可能引起设备文件状态变化的等待队列调用poll_wait(),将对应的等待队列头添加到poll_table.然后,返回表示是否能对设备进行无阻塞读写访问的掩码。在上面提到了一个poll_wait()函数,它的原型:

void poll_wait(struct file *filp, wait_queue_head_t *queue, poll_table *wait);

经过以上驱动程序的poll()函数应该返回设备资源的可获取状态,即POLLIN,POLLOUT,POLLPRI,POLLERR,POLLNVAL等宏的位"或"结果.

常量说明

POLLIN普通或优先级带数据可读

POLLRDNORM普通数据可读

POLLRDBAND优先级带数据可读

POLLPRI高优先级数据可读

POLLOUT普通数据可写

POLLWRNORM普通数据可写

POLLWRBAND优先级带数据可写

POLLERR发生错误

POLLHUP发生挂起

POLLNVAL描述字不是一个打开的文件

 

基于前面阻塞/非阻塞的文章sample中添加poll函数,并重写app测试程序。

fellowmisc.c

#include <linux/poll.h>

unsigned int fellowmisc_poll(struct file *filep, poll_table *wait)
{
  unsigned int mask = 0;
  struct fellowmisc_dev *devp = (struct fellowmisc_dev*)filep->private_data;
  poll_wait(filep, &(devp->inq), wait);//将inq加入到poll_table中。
  poll_wait(filep, &(devp->outq), wait);//将outq加入到poll_table中。
  if (devp->free > 0)//有空余空间,可写
  {
    mask |= POLLOUT | POLLWRNORM;
  }
  if (devp->buffer_size - devp->free > 0)//buffer有数据,可读。
  {
    mask |= POLLIN | POLLRDNORM;
  }
  return mask;
}
static const struct file_operations fellowmisc_fops ={
.owner = THIS_MODULE,
.open = fellowmisc_open,
.release = fellowmisc_release,
.unlocked_ioctl = fellowmisc_ioctl,
.read = fellowmisc_read,
.write = fellowmisc_write,
.poll = fellowmisc_poll,
};

app.c

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include "fellowmisc.h"
int main(int argc, char **argv)
{
  int fd = -1;
  int ret = 0;
  fd_set rfds, wfds;
  fd = open("/dev/fellowmisc", O_RDWR);
  if (fd < 0)
  {
    printf("open fail:%s\n", strerror(errno));
    return -1;
  }
  while (1)
  {
    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    FD_SET(fd, &rfds);
    FD_SET(fd, &wfds);
    select(fd + 1, &rfds, &wfds, NULL, 0);
    if (FD_ISSET(fd, &rfds))
    {
      printf("Device can be read now\n");
      char readdata[8];
      memset(readdata, 0, sizeof(readdata));
      if (ret = read(fd, readdata, sizeof(readdata))< 0)
      {
        printf("read fail:%s\n", strerror(errno));
      }
      else
      {
        printf("readdata:%s, ret= %d\n", readdata, ret);
      }
    }
    if (FD_ISSET(fd, &wfds))
    {
      printf("Device can be written now\n");
      char writedata[8] = "abcdefg";
      if ((ret = write(fd, writedata, sizeof(writedata)))< 0)
      {
        printf("write fail:%s\n", strerror(errno));
      }
      else
      {
        printf("writedata:%s, ret: %d\n", writedata, ret);
      }
    }
  }

  close(fd);
  return 0;
}

posted @ 2017-01-12 21:30  fellow_jing  阅读(418)  评论(0编辑  收藏  举报