poll()函数的使用
2015-07-04 21:07
211 查看
poll函数用于监测多个等待事件,若事件未发生,进程睡眠,放弃CPU控制权,若监测的任何一个事件发生,poll将唤醒睡眠的进程,并判断是什么等待事件发生,执行相应的操作。poll函数退出后,struct pollfd变量的所有值被清零,需要重新设置。
示例是使用poll函数来监测按键的输入
示例是使用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; //唤醒中断的条件标记,1时满足唤醒条件,静态全局变量 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) { // wait_event_interruptible(wq,key_event); //若key_event为0,从此处将进程放入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; //返回事件记录,返回0则表示等待事件超时 } //设置寄存器,申请中断号等在open函数中完成 static int key_open(struct inode *inode,struct file *filp) { int ret; s3c2410_gpio_cfgpin(key,key_cfg); //设置引脚功能 s3c2410_gpio_pullup(key,1); //第二个参数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); //监测event,一个对象,等待5000毫秒后超时,-1为无限等待 //判断poll的返回值,负数是出错,0是设定的时间超时,整数表示等待的时间发生 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; }
相关文章推荐
- 随笔1
- 在Sublime Text中运行Python文件
- Java常见错误
- NSDate使用
- [转]java基本类型(内置类型)取值范围
- 虚拟现实与游戏合体 真能成为撬杠?
- 怎么让织梦每个页面都调用全站最新文章
- UILabel和UIImageView的使用
- 手动添加PCH文件
- ROS安装教程
- 数据库的范式(1NF、2NF、3NF、BNCF)
- Labview生成exe可执行文件后相对路径无法使用
- BroadcastReceiver概述
- error C2065:未声明的标识符错误
- 易經大意原稿(頁單位) 376-400
- java学习10--循环结构while练习
- 欢迎使用CSDN-markdown编辑器
- Visual Studio 连接 SQL Server 的connectionStringz和
- 最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等
- wps常用快捷键