poll()函数的使用
分类: LINUX
poll函数用于监测多个等待事件,若事件未发生,进程睡眠,放弃CPU控制权,若监测的任何一个事件发生,poll将唤醒睡眠的进程,并判断是什么等待事件发生,执行相应的操作。poll函数退出后,struct pollfd变量的所有值被清零,需要重新设置。
示例是使用poll函数来监测按键的输入
----------------------------------------------------------------------------------------------------------
驱动代码:
- #include <linux/config.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <linux/init.h>
- #include <linux/devfs_fs_kernel.h>
- #include <linux/miscdevice.h>
- #include <linux/delay.h>
- #include <asm/irq.h>
- #include <asm/arch/regs-gpio.h>
- #include <asm/hardware.h>
- #include <linux/cdev.h>
- #include <linux/mm.h>
- #include <linux/interrupt.h>
- #include <linux/poll.h>
- #include <asm/uaccess.h>
- #include <asm/ioctl.h>
- #include <asm/arch/regs-irq.h>
- #include <asm/io.h>
- #define key S3C2410_GPF0
- #define key_irq IRQ_EINT0 //IRQ_EINT0是中断号
- #define key_cfg S3C2410_GPF0_EINT0 //设置为外部中断功能
- #define DEVICE_NAME "key"
//注意加上双引号 - #define DEVICE_MAJOR major
- #define DEVICE_MINOR 0
- static dev_t dev;
//dev_t类型用于存放主设备号和次设备号 - static
int major; - struct cdev *p_cdev;
//声明一个指向字符设备结构的指针 - static
int key_event=0;
时满足唤醒条件,静态全局变量 - static
int key_value=1;
//按键键值 - static DECLARE_WAIT_QUEUE_HEAD(wq);
//调用宏定义,静态创建一个名为wq的等待队列 - static
void key_interrupt(void)
//中断处理函数,注册中断时已注册了中断程序的入口地址 - {
- key_value=s3c2410_gpio_getpin(key);
- key_event=1;
//唤醒标记置位,表示条件达到,可以唤醒进程继续执行 - wake_up_interruptible(&wq);
//调用宏定义,唤醒标记置位后调用此函数,&wq是队列入口地址 - }
- static
int key_read(struct
file
*filp,char __user *buff,size_t count,loff_t *offp) - {
- ,从此处将进程放入wq等待队列休眠,等待中断;key_event==1时,此宏不执行操作
- //调用poll的时候来等待,这里可以不用wait_event_interrupt()
- key_value=s3c2410_gpio_getpin(key);
- copy_to_user(buff,&key_value,sizeof(key_event));
//将&key_value地址的值从内核空间复制到用户空间 - key_event=0;
//完成中断操作,将唤醒标记清零,继续休眠 - return 0;
- }
- static unsigned int key_poll(struct
file
*filp,poll_table *wait) - {
- unsigned int mask=0;
//用来记录发生的事件,以unsigned int类型返回 - poll_wait(filp,&wq,wait);
//将当前进程添加到wq等待队列中 - if(key_event==1)mask|=POLLIN|POLLRDNORM;
//中断事件发生,这时有数据可读,在mask中标记是可读事件发生 - return mask;
则表示等待事件超时 - }
- //设置寄存器,申请中断号等在open函数中完成
- static
int key_open(struct inode *inode,struct
file
*filp) - {
- int ret;
- s3c2410_gpio_cfgpin(key,key_cfg);
//设置引脚功能 - s3c2410_gpio_pullup(key,1);
为禁止内部上拉 - ret=request_irq(key_irq,(void
*)key_interrupt,SA_INTERRUPT,DEVICE_NAME,NULL);
//注册中断,中断不共享时最后一个参数为NULL - if(ret)
{ - printk("Could not register interrupt\n");
- return ret;
- }
- set_irq_type(key_irq,IRQT_BOTHEDGE);
//设置中断方式为双边触发 - return 0;
- }
- static
int key_close(struct inode *inode,struct
file
*filp) - {
- free_irq(key_irq,NULL);
//中断无共享时第二个参数为NULL - return 0;
- }
- static
struct file_operations key_fops={ - .owner=THIS_MODULE,
- .open=key_open,
- .release=key_close,
- .read=key_read,
- .poll=key_poll,
- };
- int key_init(void)
- {
- int ret;
- ret=alloc_chrdev_region(&dev,DEVICE_MINOR,1,DEVICE_NAME);
//采用主设备号动态分配 - if(ret<0){
- printk("Register /dev/key failed!\n");
- return ret;
- }
- else printk("Register /dev/key successfully!\n");
- major=MAJOR(dev);
//取得分配到的主设备号 - p_cdev=cdev_alloc();
//申请一个字符设备结构并返回指向它的指针 - cdev_init(p_cdev,&key_fops);
//相当于p_cdev->ops=&key_fops - p_cdev->owner=THIS_MODULE;
- ret=cdev_add(p_cdev,dev,1);
//向系统添加这个字符设备 - if(ret<0){
- printk("Add cdev failed!\n");
- return ret;
- }
- devfs_mk_cdev(dev,S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,DEVICE_NAME);
- return 0;
- }
- void key_exit(void)
- {
- unregister_chrdev_region(dev,1);
- cdev_del(p_cdev);
//删除字符设备 - devfs_remove(DEVICE_NAME);
- printk("Device unregister!\n");
- }
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("HJW");
- module_init(key_init);
- module_exit(key_exit);
- ---------------------------------------------------------------------------------------------------
- 测试程序代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
/*文件控制*/ - #include <sys/select.h>
- #include <sys/time.h>
/*时间方面的函数*/ - #include <errno.h>
/*有关错误方面的宏*/ - #include<sys/poll.h>
//poll() - #include<fcntl.h>
- #include<string.h>
//memset() - int main(void)
- {
- int fd,key_value,ret;
- struct pollfd event;
//创建一个struct pollfd结构体变量,存放文件描述符、要等待发生的事件 - fd=open("/dev/key",O_RDWR);
- if(fd<0){
- perror("open /dev/key error!\n");
- exit(1);
- }
- printf("open /dev/key sucessfully!\n");
- while(1){
//poll结束后struct pollfd结构体变量的内容被全部清零,需要再次设置 - memset(&event,0,sizeof(event));
//memst函数对对象的内容设置为同一值 - event.fd=fd;
//存放打开的文件描述符 - event.events=POLLIN;
//存放要等待发生的事件 - ret=poll((struct pollfd *)&event,1,5000);
毫秒后超时,-1为无限等待 - 是设定的时间超时,整数表示等待的时间发生
- if(ret<0){
- printf("poll error!\n");
- exit(1);
- }
- if(ret==0){
- printf("Time out!\n");
- continue;
- }
- if(event.revents&POLLERR){
//revents是由内核记录的实际发生的事件,events是进程等待的事件 - printf("Device error!\n");
- exit(1);
- }
- if(event.revents&POLLIN){
- read(fd,&key_value,sizeof(key_value));
- printf("Key value is '%d'\n",key_value);
- }
- }
- close(fd);
- return 0;
- }
poll()函数的使用的更多相关文章
- linux poll函数
poll函数与select函数差不多 函数原型: #include <poll.h> int poll(struct pollfd fd[], nfds_t nfds, int timeo ...
- poll函数
poll函数与select函数的功能基本一样,其定义如下: #include <poll.h> int poll(struct pollfd fds[], nfds_t nfds, int ...
- select与poll函数介绍
select与poll函数介绍 在所有依从POSIX的平台上,select函数使我们可以执行I/O多路转接.传向select的参数告诉内核: 1)我们所关心的描述符 2)对于每个描述符我们所关心的状态 ...
- I/O多路复用——select函数与poll函数
1 区别 同:(1)机制类似,本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理.(2)包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就 ...
- poll函数和串口设置
2015.1.24 今天星期六,多云,早晨8:17起床的,今天是来南京起床最迟的一天,因为昨晚睡得有点迟,今天又不用上课,整个人有点放松.收拾好来到教室,教室门没有开,胡明也到了,其他人还在宿舍睡觉, ...
- [转载] poll()函数
原地址:http://baike.baidu.com/view/2997591.htm poll()函数:这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,下面是这个函 ...
- I/O多路转接之poll 函数
poll 一.poll()函数: 这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,自认为poll和select大同小异,下面是这个函数的声明: #include < ...
- UNIX网络编程——select函数的并发限制和 poll 函数应用举例
一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置, ...
- 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数
本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...
随机推荐
- nodejs的初学
1.启服务器.先server.js,再命令行输入命令node server.js,打开浏览器输入http://127.0.0.1:2016可以看到有内容输出. server.js代码如下: var h ...
- 动态创建script在IE中缓存js文件时导致编码不正确bug
$.each(scripts, function(){ if(!jsExist(this.src)){ var s = document.createElement("SCRIPT" ...
- [课程设计]任务进度条&开发日志目录
任务进度条&开发日志目录 周期 时间 任务 Sprint One 11.14 ● Scrum团队分工及明确任务1.0 Sprint One 11.15 ● Scr ...
- 【HDU2255】奔小康赚大钱-KM算法
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description ...
- 关于sql 的列转行
select * from TbaleOne unpivot(qty ])) as up go select * from TableTwo unpivot(grate for subject in ...
- Uva 1629 切蛋糕
题目链接:https://vjudge.net/contest/146179#problem/B 题意:一个矩形蛋糕上有好多个樱桃,现在要做的就是切割最少的距离,切出矩形形状的小蛋糕,让每个蛋糕上都有 ...
- AfxBeginThread中使用updatedata出错
原因:MFC对象不支持多线程操作,不能供多个线程进程使用,所以尽量不要在线程里面更新界面. 解决办法: 1.将工程改为release 2.使用控件来SetWindowText 3.在线程里面发送消息 ...
- 公钥私钥和RSA算法
1, RSA算法原理(一) http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html 2, RSA算法原理(二) http: ...
- Bootstrap_列表组
一.基本列表组 列表组是Bootstrap框架新增的一个组件,可以用来制作列表清单.垂直导航等效果,也可以配合其他的组件制作出更漂亮的组件. <ul class="list-grou ...
- Oracle(创建index)
概念: 1. 类似书的目录结构 2. Oracle 的“索引”对象,与表关联的可选对象,提高SQL查询语句的速度 3. 索引直接指向包含所查询值的行的位置,减少磁盘I/O 4. 与所索引的表是相互独立 ...