设为首页 加入收藏

TOP

poll()函数的使用(一)
2014-11-23 23:11:40 来源: 作者: 【 】 浏览:5
Tags:poll 函数 使用
poll函数用于监测多个等待事件,若事件未发生,进程睡眠,放弃CPU控制权,若监测的任何一个事件发生,poll将唤醒睡眠的进程,并判断是什么等待事件发生,执行相应的操作。poll函数退出后,struct pollfd变量的所有值被清零,需要重新设置。
示例是使用poll函数来监测按键的输入
----------------------------------------------------------------------------------------------------------
驱动代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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");
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇如何使用C语言写: Generic Stack 下一篇C语言中的正则表达式

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: