POLL操作

1、POLL运行过程:

poll是一个系统调用,其内核入口函数为sys_poll,sys_poll差点儿不做不论什么处理直接调用do_sys_poll,do_sys_poll的运行过程能够分为三个部分:

1,将用户传入的pollfd数组复制到内核空间,由于拷贝操作和数组长度相关。时间上这是一个O(n)操作,这一步的代码在do_sys_poll中包含从函数開始到调用do_poll前的部分。

2,查询每一个文件描写叙述符相应设备的状态,假设该设备尚未就绪,则在该设备的等待队列中增加一项并继续查询下一设备的状态。

查询全然部设备后假设没有一个设备就绪,这时则须要挂起当前进程等待。直到设备就绪或者超时,挂起操作是通过调用schedule_timeout执行的。设备就绪后进程被通知继续执行,这时再次遍历全部设备,以查找就绪设备。这一步由于两次遍历全部设备。时间复杂度也是O(n),这里面不包含等待时间。相关代码在do_poll函数中。

 3,将获得的数据传送到用户空间并运行释放内存和剥离等待队列等善后工作,向用户空间拷贝数据与剥离等待队列等操作的的时间复杂度相同是O(n),详细代码包含do_sys_poll函数中调用do_poll后到结束的部分。

2、代码编写

1、在file_operations结构体中加入 poll

static struct file_operations button_sdv_fops =
{
.owner = THIS_MODULE,
.open = button_dev_open,
.read = button_dev_read,
.release = button_dev_close,
.poll = button_dev_poll,
};

2、完毕 button_dev_poll函数

static unsigned int button_dev_poll(struct file *file, poll_table * wait)
{
unsigned int mask =0;
poll_wait(file, &button_wait_q, wait);//把当前进程挂到队列里面,不会立马休眠 if(ev_press)
mask |=POLLIN |POLLRDNORM; return mask;
}

当中ev_press是上一篇博文中的中断事件发生标志,假设中断动作发生,则mask值将被告诉内核。当中 mask的值的含义:

常量
说明
POLLIN
普通或优先级带数据可读
POLLRDNORM
普通数据可读
POLLRDBAND
优先级带数据可读
POLLPRI
高优先级数据可读
POLLOUT
普通数据可写
POLLWRNORM
普通数据可写
POLLWRBAND
优先级带数据可写
POLLERR
错误发生
POLLHUP
发生挂起
POLLNVAL
描写叙述字不是一个打开的文件

3、測试程序编写

ret = poll(fds, 1, 3000);

poll函数原型:

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

当中:pollfd结构体为:

struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};

fd是要查询的设备。events是期望获得的事件,这里我们将他设置为:POLLIN

fds定义一个数组,存放须要poll的全部设备。poll操作会同一时候查询这些设备。

nfds为查询的文件数量

timeout为超时时间

驱动程序完整代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/irqs.h>//这个在/opt/EmbedSky/linux-2.6.30.4/arch/arm/mach-s3c2410/include/mach 路径
#include <linux/interrupt.h>
#include <linux/poll.h> MODULE_LICENSE("Dual BSD/GPL"); static struct class *buttondrv_class;
static struct class_devices *buttondrv_class_dev; /* */
static DECLARE_WAIT_QUEUE_HEAD(button_wait_q);
/*中断事件标志,中断服务程序将他置1,read函数将他置0*/
static volatile int ev_press =0; volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL; static unsigned keyval; struct pin_desc{
unsigned int pin;
unsigned int key_value;
};
/*按键按下时是:0x01 0x02 0x03 0x04*/
/*按键松开时是:0x81 0x82 0x83 0x84*/
struct pin_desc pins_desc[4] =
{
{S3C2410_GPF1,0x01},
{S3C2410_GPF4,0x02},
{S3C2410_GPF2,0x03},
{S3C2410_GPF0,0x04},
};
/*
* 确定按键值
*/
static irqreturn_t buttons_irq(int irq,void *dev_id)
{
struct pin_desc * pindesc = (struct pin_desc *) dev_id;
unsigned int pinval;
pinval = s3c2410_gpio_getpin(pindesc -> pin);
if(pinval)//松开
{
keyval = 0x80|pindesc->key_value;
}
else
{
keyval = pindesc->key_value;
}
ev_press =1;//中断发生
wake_up_interruptible(&button_wait_q);
printk("button is pressed : %d \n",irq);
return IRQ_HANDLED;
}
static int button_dev_open(struct inode *inode ,struct file* file)
{
//配置按键的引脚 GPF0,1,2,4为输入引脚
request_irq(IRQ_EINT1,buttons_irq, IRQ_TYPE_EDGE_BOTH,"key1",&pins_desc[0]);
request_irq(IRQ_EINT4,buttons_irq, IRQ_TYPE_EDGE_BOTH,"key2",&pins_desc[1]);
request_irq(IRQ_EINT2,buttons_irq, IRQ_TYPE_EDGE_BOTH,"key3",&pins_desc[2]);
request_irq(IRQ_EINT0,buttons_irq, IRQ_TYPE_EDGE_BOTH,"key4",&pins_desc[3]); return 0;
}
ssize_t button_dev_read(struct file *file,char __user *buf,size_t size,loff_t *ppos)
{
if(size !=1)
{
return -EINVAL;
}
/*假设没有按键动作发生 就休眠*/
wait_event_interruptible(button_wait_q,ev_press);
/*假设有按键动作发生,直接返回*/
copy_to_user(buf,&keyval,1);
ev_press = 0;
return 0;
}
int button_dev_close(struct inode* inode ,struct file *file)
{
free_irq(IRQ_EINT1,&pins_desc[0]);
free_irq(IRQ_EINT4,&pins_desc[1]);
free_irq(IRQ_EINT2,&pins_desc[2]);
free_irq(IRQ_EINT0,&pins_desc[3]); return 0;
}
static unsigned int button_dev_poll(struct file *file, poll_table * wait)
{
unsigned int mask =0;
poll_wait(file, &button_wait_q, wait);//把当前进程挂到队列里面,不会立马休眠 if(ev_press)
mask |=POLLIN |POLLRDNORM; return mask;
}
static struct file_operations button_sdv_fops =
{
.owner = THIS_MODULE,
.open = button_dev_open,
.read = button_dev_read,
.release = button_dev_close,
.poll = button_dev_poll,
};
int major;
static int button_dev_init(void)//入口函数
{
major = register_chrdev(0,"button_drv",&button_sdv_fops); buttondrv_class = class_create(THIS_MODULE,"button_drv");
if(IS_ERR(buttondrv_class))
return PTR_ERR(buttondrv_class);
buttondrv_class_dev= device_create(buttondrv_class,NULL,MKDEV(major,0),NULL,"wq_button");
if(unlikely(IS_ERR(buttondrv_class_dev)))
return PTR_ERR(buttondrv_class_dev); /*映射物理地址*/
gpfcon = (volatile unsigned long *) ioremap(0x56000050 ,16);
gpfdat = gpfcon + 1; return 0;
}
static void button_dev_exit(void)
{
unregister_chrdev(major,"button_drv");
device_unregister(buttondrv_class_dev);
class_destroy(buttondrv_class); iounmap(gpfcon);
}
module_init(button_dev_init);
module_exit(button_dev_exit);

測试程序完整代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h> int main(int argc, char **argv)
{
int ret=0;
int cnt=0;
int fd;
unsigned char key_val;
struct pollfd fds[1];
fd = open("/dev/wq_button", O_RDWR);
if(fd<0)
{
printf("can't open \n");
}
fds[0].fd = fd;
fds[0].events = POLLIN;
while(1)
{
ret = poll(fds, 1, 3000);
if(ret == 0)
{
printf("time out \n");
}
else
{
read(fd,&key_val,1);
printf("key_val = 0x%x\n",key_val);
} }
return 0;
}

linux驱动之poll操作的更多相关文章

  1. Linux驱动之poll机制的理解与简单使用

    之前在Linux驱动之按键驱动编写(中断方式)中编写的驱动程序,如果没有按键按下.read函数是永远没有返回值的,现在想要做到即使没有按键按下,在一定时间之后也会有返回值.要做到这种功能,可以使用po ...

  2. (十二)Linux内核驱动之poll和select

    使用非阻塞 I/O 的应用程序常常使用 poll, select, 每个允许一个进程来决定它是否可读或者写一个或多个文件而不阻塞. 这些调用也可阻塞进程直到任何一个给定集合的文件描述符可用来读或写.  ...

  3. 嵌入式Linux驱动学习之路(十二)按键驱动-poll机制

    实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键 ...

  4. linux驱动编写之poll机制

    一.概念 1.poll情景描述 以按键驱动为例进行说明,用阻塞的方式打开按键驱动文件/dev/buttons,应用程序使用read()函数来读取按键的键值.这样做的效果是:如果有按键按下了,调用该re ...

  5. Linux驱动学习步骤(转载)

    1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, ls ...

  6. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  7. Linux驱动设计——字符设备驱动(一)

    Linux字符设别驱动结构 cdev结构体 struct cdev { struct kobject kobj; struct module *owner; const struct file_ope ...

  8. Linux驱动开发学习的一些必要步骤

      1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, ...

  9. 【Linux驱动】字符设备驱动

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...

随机推荐

  1. 样条函数(spline function)—— 分段多项式函数(piecewise polynomial function)

    1. 分段多项式函数 样条函数是某种意义上的分段函数. Spline (mathematics) - Wikipedia 最简单的样条函数是一种分段多项式函数(piecewise polynomial ...

  2. Node.js:目录

    ylbtech-Node.js:目录 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部 1. http://www.runoob.com/nodejs/nodejs ...

  3. hiho一下第76周《Suzhou Adventure》

    我是菜鸡,我是菜鸡,我是菜鸡....重要的事说三遍 算是第一次做树形dp的题吧,不太难.. 园林构成一棵树,root为1,Hi从root出发,有k个园林必须玩,每个园林游玩后会得到权值w[i],最多玩 ...

  4. Python 3.x 判断 dict 是否包含某个键

    Python 3.x不再支持 has_key() 函数,而被__contains__('key')所替代,会返回bool,可以用其做判断. 代码示例: >>> user = 'dad ...

  5. 【React Natvie】React-native-swiper的安装和配置【ES6】

    react-native-swiper轮播图,是我们开发中特别常见的效果,首先感谢编写react-native-swiper的大神,让我们方便了很多.这个框架主要是用来做轮播图,焦点图等,内置了各种样 ...

  6. Ajax请求成功但是一直进入error的原因

    1.在1.3版本的jQuery以后,严格要求了json格式,如果返回的值不是json格式,他就会执行error函数. 所以如果想让他走success函数的话,还是在后台把数据格式化成json格式吧. ...

  7. SVO在ROS下的配置与运行

    最近在做实验的时候,需要配置SVO,下面讲讲其中的过程以及遇到的问题: 首先说明配置环境:Ubuntu 14.04 + ROS indigo,ROS的安装我参考了ROS的官网上给出的教程:http:/ ...

  8. Thread pool引起的程序连接数据库响应慢

    数据库版本:percona-mysql 5.6.16 ​在很长一段时间,都会出现程序连接数据库,出现响应慢的情况,正常在几到几十毫秒之间,但是偶尔会出现上百毫秒的情况: 开始由于开发重新设置并调整过程 ...

  9. ORACLE 11g 导出数据

    ORACLE 11g 导出 表的时候 不会导出空表 导出空表操作步骤 :(使用PLSQL) 1.打开SQL window 执行下面的 SQL Select 'alter table '||table_ ...

  10. javascript中函数表达式的问题讨论

    #函数表达式 ##函数声明和函数表达式的区别 函数的定义有两种形式,一种是函数声明,一种是函数表达式 使用声明时,要注意函数声明提升现象,比如说在if语句中使用声明会出错,但是表达式就不存在这个问题 ...