按下按键是驱动程序通知应用程序
应用程序里面要注册信号处理函数
驱动程序给应用程序发信号
发给谁,这就要应用程序告诉驱动pid了
怎么发,是驱动里面调用kill_fasync
为了使设备支持异步通知机制,驱动程序涉及以下3项工作
1.支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID
不过此项工作已经有内核完成,设备驱动无需处理
2.支持F_SETFL命令的处理,每当FASYNC标志改变时,驱动程序中的fasync()函数将得以执行
驱动中应该实现fasync函数
3.在设备资源可以获得时,调用kill_fasync()函数激发相应的信号
应用程序会调用fcntl(fd,F_SETOWN,pid)把它的pid告诉驱动程序
然后还要读出flags
oflags = fcntl(fd,F_GETFL)
要把这个flag进行修改fcntl(fd,F_SETFL,oflags | FASYNC);当应用程序调用这个接口的时候,fasync_helper就会被调用
#include <linux/device.h>#include <linux/interrupt.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/irq.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <mach/gpio.h>#include<linux/cdev.h>#include <linux/poll.h>int key_id;struct cdev cdev;dev_t devno;static struct fasync_struct *button_fasync;/*定义并初始化等待队列的头*/static DECLARE_WAIT_QUEUE_HEAD(key_qaq);/*中断事件标志,中断服务程序将它置为1,read函数将它置为0*/unsigned int wait_val=0;struct class *my_class;static irqreturn_t key_func(int irq,void *dev_id){key_id=(int)dev_id;/*唤醒*/wait_val=1;wake_up(&key_qaq);kill_fasync(&button_fasync,SIGIO,POLL_IN);//发出信号return 0;}static int key_open(struct inode *inode,struct file *file){request_irq(IRQ_EINT(16),key_func,IRQF_TRIGGER_FALLING,"k1",1);request_irq(IRQ_EINT(17),key_func,IRQF_TRIGGER_FALLING,"k2",2);request_irq(IRQ_EINT(18),key_func,IRQF_TRIGGER_FALLING,"k3",3);request_irq(IRQ_EINT(19),key_func,IRQF_TRIGGER_FALLING,"k4",4);request_irq(IRQ_EINT(24),key_func,IRQF_TRIGGER_FALLING,"k5",5);request_irq(IRQ_EINT(25),key_func,IRQF_TRIGGER_FALLING,"k6",6);request_irq(IRQ_EINT(26),key_func,IRQF_TRIGGER_FALLING,"k7",7);request_irq(IRQ_EINT(27),key_func,IRQF_TRIGGER_FALLING,"k8",8);return 0;}static int key_close(struct inode *inode,struct file *file){free_irq(IRQ_EINT(16),1);free_irq(IRQ_EINT(17),2);free_irq(IRQ_EINT(18),3);free_irq(IRQ_EINT(19),4);free_irq(IRQ_EINT(24),5);free_irq(IRQ_EINT(25),6);free_irq(IRQ_EINT(26),7);free_irq(IRQ_EINT(27),8);return 0;}ssize_t key_read(struct file *filp, char __user *buf, size_t size,loff_t *pos){/*如果没有按键按下,休眠,让出CPU*/wait_event(key_qaq,wait_val);/*如果有按键按下*/copy_to_user(buf,&key_id,sizeof(key_id)); wait_val=0;return 0;}static int key_fasync(int fd,struct file *filp,int on){return fasync_helper(fd,filp,on,&button_fasync);//初始化button_fasync这个结构体;}static unsigned key_poll(struct file *file, poll_table *wait){unsigned int mask=0;poll_wait(file,&key_qaq,wait);/*不会立即休眠,只是挂在那个队列上面去*/if(wait_val)mask |= POLLIN | POLLRDNORM;return mask;}static struct file_Operations key_fops ={.owner = THIS_MODULE,.open = key_open,.release = key_close,.read = key_read,.poll = key_poll,.fasync = key_fasync,};static int __init key_fasync_init(void){cdev_init(&cdev,&key_fops);alloc_chrdev_region(&devno, 0 , 1 , "mykey_fasync");cdev_add(&cdev, devno, 1);my_class = class_create(THIS_MODULE, "key_fasync_class");if(IS_ERR(my_class)){PRintk("Err: failed in creating class./n");return -1;}device_create(my_class, NULL, devno,NULL,"key_fasync_driver");return 0;}static void key_fasync_exit(void){device_destroy(my_class,devno);class_destroy(my_class);cdev_del(&cdev);unregister_chrdev_region(devno,1);}module_init(key_fasync_init);module_exit(key_fasync_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("EIGHT_FIVE");测试程序如下:
#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>#include<poll.h>#include<signal.h>#include<unistd.h>#include<fcntl.h>int fd;void my_signal_func(int signum){unsigned int key_val;read(fd,&key_val,4);printf("key_val = %d/n",key_val);}int main(int argc,char **argv){signal(SIGIO,my_signal_func);int flag;fd=open("/dev/key_fasync_driver",O_RDWR);if(fd<0){printf("can't open!/n");}fcntl(fd,F_SETOWN,getpid());flag=fcntl(fd,F_GETFL);fcntl(fd,F_SETFL,flag | FASYNC);while(1);return 0;}
新闻热点
疑难解答