使用非阻塞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;
}

设备驱动基础学习--poll的更多相关文章

  1. 设备驱动基础学习--platform driver简单实现

    platform是一条虚拟的总线.设备用platform_device表示,驱动用platform_driver进行注册,Linux platform driver机制和传统的device drive ...

  2. 设备驱动基础学习--misc device简单实现

    在Linux驱动中把无法归类的五花八门的设备定义为混杂设备(用miscdevice结构体表述).miscdevice共享一个主设备号MISC_MAJOR(即10),但次设备号不同. 所有的miscde ...

  3. 设备驱动基础学习--/proc下增加节点

    在需要创建一个由一系列数据顺序组合而成的/proc虚拟文件或一个较大的/proc虚拟文件时,推荐使用seq_file接口. 数据结构struct seq_fille定义在include/linux/s ...

  4. Hasen的linux设备驱动开发学习之旅--时钟

    /** * Author:hasen * 參考 :<linux设备驱动开发具体解释> * 简单介绍:android小菜鸟的linux * 设备驱动开发学习之旅 * 主题:时钟 * Date ...

  5. 字符设备驱动(六)按键poll机制

    title: 字符设备驱动(六)按键poll机制 tags: linux date: 2018-11-23 18:57:40 toc: true --- 字符设备驱动(六)按键poll机制 引入 在字 ...

  6. Introduction the naive“scull” 《linux设备驱动》 学习笔记

    Introduction the naive "scull" 首先.什么是scull? scull (Simple Character Utility for Loading Lo ...

  7. 【驱动】Flash设备驱动基础·NOR·NAND

    Flash存储器 ——>Flash存储器是近几年来发展最快的存储设备,通常也称作闪存.Flash属于EEPROM(电可擦除可编程只读存储器),是一类存取速度很高的存储器. ——>它既有RO ...

  8. 3.字符设备驱动------Poll机制

    1.poll情景描述 以之前的按键驱动为例进行说明,用阻塞的方式打开按键驱动文件/dev/buttons,应用程序使用read()函数来读取按键的键值. ) { read(fd, &key_v ...

  9. Linux内核分析(五)----字符设备驱动实现

    原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷, ...

随机推荐

  1. [P5490] 【模板】扫描线 - 线段树

    求 \(n\) 个矩形的面积并 Solution 将矩形转化为 \(y_1\) 位置的 + 修改 和 \(y_2\) 位置的 - 修改.然后按照 \(+y\) 顺序依次处理所有的修改,到达的一个新的位 ...

  2. nice-validator判断表单是否验证通过

    $("#formSurvery").isValid(function(is){ if(is){ alert("通过!") } } 如果is为false则表示不通 ...

  3. 502. IPO(最小堆+最大堆法 or 排序法)

    题目: 链接:https://leetcode-cn.com/problems/ipo/submissions/ 假设 力扣(LeetCode)即将开始其 IPO.为了以更高的价格将股票卖给风险投资公 ...

  4. 让Surface Shader不受光照的明暗影响

    直接上码 Shader "Custom/3DVideo" { Properties { _Color (,,,) _MainTex ("Albedo (RGB)" ...

  5. ping和tracert

    ping命令常用于测试2台主机网络是否连通 TTL的默认值有:64(linux),128(windows),255(路由器) 此例TTL是63所以选用64来减去63等于1,这是说明经过了1个路由器,没 ...

  6. 题解 CF712C 【Memory and De-Evolution】

    看到题我第一反应就是while循环 但是我竟然想正着推,失败,卡了十几分钟 后来我回来看到第三组测试数据 想到倒推 但是没坚持 于是我又卡了很久 过会我又回来想 AC了... 这个故事告诉我们,要努力 ...

  7. 解决PHP Redis扩展无法加载的问题

    最近在工作中需要使用PHP访问Redis,从https://github.com/phpredis/phpredis下载了phpredis,并且按照官方的说明进行了安装 phpize ./config ...

  8. c数据结构 -- 线性表之 复杂的链式存储结构

    复杂的链式存储结构 循环链表 定义:是一种头尾相接的链表(即表中最后一个结点的指针域指向头结点,整个链表形成一个环) 优点:从表中任一节点出发均可找到表中其他结点 注意:涉及遍历操作时,终止条件是判断 ...

  9. util之ArrayList

    Java之ArrayList 方法: add(o: E): void 在list的末尾添加一个元素o add(index: int, o: E): void 在指定的index处插入元素o clear ...

  10. bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)

    ps:这道题过的人真多啊 一道树剖的模板题 (好像还可以用lct做, 然而我并不会 代码如下 /**************************************************** ...