linux驱动的异步通知(kill_fasync,fasync)---- 驱动程序向应用程序发送信号

Posted 苏博

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux驱动的异步通知(kill_fasync,fasync)---- 驱动程序向应用程序发送信号相关的知识,希望对你有一定的参考价值。

应用程序

  1. #include <sys/types.h>  
  2. #include <sys/stat.h>  
  3. #include <fcntl.h>  
  4. #include <stdio.h>  
  5. #include <poll.h>  
  6. #include <signal.h>  
  7. #include <sys/types.h>  
  8. #include <unistd.h>  
  9. #include <fcntl.h>  
  10.   
  11.   
  12. /* fifthdrvtest  
  13.   */  
  14. int fd;  
  15.   
  16. //信号处理函数  
  17. void my_signal_fun(int signum)  
  18. {  
  19.     unsigned char key_val;  
  20.     read(fd, &key_val, 1);  
  21.     printf("key_val: 0x%x\n", key_val);  
  22. }  
  23.   
  24. int main(int argc, char **argv)  
  25. {  
  26.     unsigned char key_val;  
  27.     int ret;  
  28.     int Oflags;  
  29.   
  30.     //在应用程序中捕捉SIGIO信号(由驱动程序发送)  
  31.     signal(SIGIO, my_signal_fun);  
  32.       
  33.     fd = open("/dev/buttons", O_RDWR);  
  34.     if (fd < 0)  
  35.     {  
  36.         printf("can‘t open!\n");  
  37.     }  
  38.   
  39.     //将当前进程PID设置为fd文件所对应驱动程序将要发送SIGIO,SIGUSR信号进程PID  
  40.     fcntl(fd, F_SETOWN, getpid());  
  41.       
  42.     //获取fd的打开方式  
  43.     Oflags = fcntl(fd, F_GETFL);   
  44.   
  45.     //将fd的打开方式设置为FASYNC --- 即 支持异步通知  
  46.     // 该行代码执行会触发 驱动程序中 file_operations->fasync 函数 ------fasync函数调用 fasync_helper初始化一个fasync_struct结构体,该结构体描述了将要发送信号的进程 PID (fasync_struct->fa_file->f_owner->pid)  
  47.     fcntl(fd, F_SETFL, Oflags | FASYNC);  
  48.   
  49.   
  50.     while (1)  
  51.     {  
  52.         sleep(1000);  
  53.     }  
  54.       
  55.     return 0;  
  56. }  


驱动程序

  1. #include <linux/module.h>  
  2. #include <linux/kernel.h>  
  3. #include <linux/fs.h>  
  4. #include <linux/init.h>  
  5. #include <linux/delay.h>  
  6. #include <linux/irq.h>  
  7. #include <asm/uaccess.h>  
  8. #include <asm/irq.h>  
  9. #include <asm/io.h>  
  10. #include <asm/arch/regs-gpio.h>  
  11. #include <asm/hardware.h>  
  12. #include <linux/poll.h>  
  13.   
  14.   
  15. static struct class *fifthdrv_class;  
  16. static struct class_device  *fifthdrv_class_dev;  
  17.   
  18. //volatile unsigned long *gpfcon;  
  19. //volatile unsigned long *gpfdat;  
  20.   
  21. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  
  22.   
  23. /* 中断事件标志, 中断服务程序将它置1,fifth_drv_read将它清0 */  
  24. static volatile int ev_press = 0;  
  25.   
  26. static struct fasync_struct *button_async;  
  27.   
  28.   
  29. struct pin_desc{  
  30.     unsigned int pin;  
  31.     unsigned int key_val;  
  32. };  
  33.   
  34.   
  35. /* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 */  
  36. /* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */  
  37. static unsigned char key_val;  
  38.   
  39. /* 
  40.  * K1,K2,K3,K4对应GPG0,GPG3,GPG5,GPG6 
  41.  */  
  42.   
  43. struct pin_desc pins_desc[4] = {  
  44.     {S3C2410_GPG0, 0x01},  
  45.     {S3C2410_GPG3, 0x02},  
  46.     {S3C2410_GPG5, 0x03},  
  47.     {S3C2410_GPG6, 0x04},  
  48. };  
  49.   
  50.   
  51. /* 
  52.   * 确定按键值 
  53.   */  
  54. static irqreturn_t buttons_irq(int irq, void *dev_id)  
  55. {  
  56.     struct pin_desc * pindesc = (struct pin_desc *)dev_id;  
  57.     unsigned int pinval;  
  58.       
  59.     pinval = s3c2410_gpio_getpin(pindesc->pin);  
  60.   
  61.     if (pinval)  
  62.     {  
  63.         /* 松开 */  
  64.         key_val = 0x80 | pindesc->key_val;  
  65.     }  
  66.     else  
  67.     {  
  68.         /* 按下 */  
  69.         key_val = pindesc->key_val;  
  70.     }  
  71.   
  72.     ev_press = 1;                  /* 表示中断发生了 */  
  73.     wake_up_interruptible(&button_waitq);   /* 唤醒休眠的进程 */  
  74.       
  75.         //发送信号SIGIO信号给fasync_struct 结构体所描述的PID,触发应用程序的SIGIO信号处理函数  
  76.     kill_fasync (&button_async, SIGIO, POLL_IN);  
  77.       
  78.     return IRQ_RETVAL(IRQ_HANDLED);  
  79. }  
  80.   
  81. static int fifth_drv_open(struct inode *inode, struct file *file)  
  82. {  
  83.     /* GPG0,GPG3,GPG5,GPG6为中断引脚: EINT8,EINT11,EINT13,EINT14 */  
  84.     request_irq(IRQ_EINT8,  buttons_irq, IRQT_BOTHEDGE, "K1", &pins_desc[0]);  
  85.     request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "K2", &pins_desc[1]);  
  86.     request_irq(IRQ_EINT13, buttons_irq, IRQT_BOTHEDGE, "K3", &pins_desc[2]);  
  87.     request_irq(IRQ_EINT14, buttons_irq, IRQT_BOTHEDGE, "K4", &pins_desc[3]);     
  88.   
  89.     return 0;  
  90. }  
  91.   
  92. ssize_t fifth_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)  
  93. {  
  94.     if (size != 1)  
  95.         return -EINVAL;  
  96.   
  97.     /* 如果没有按键动作, 休眠 */  
  98.     wait_event_interruptible(button_waitq, ev_press);  
  99.   
  100.     /* 如果有按键动作, 返回键值 */  
  101.     copy_to_user(buf, &key_val, 1);  
  102.     ev_press = 0;  
  103.       
  104.     return 1;  
  105. }  
  106.   
  107.   
  108. int fifth_drv_close(struct inode *inode, struct file *file)  
  109. {  
  110.     free_irq(IRQ_EINT8,  &pins_desc[0]);  
  111.     free_irq(IRQ_EINT11, &pins_desc[1]);  
  112.     free_irq(IRQ_EINT13, &pins_desc[2]);  
  113.     free_irq(IRQ_EINT14, &pins_desc[3]);  
  114.     return 0;  
  115. }  
  116.   
  117. static unsigned fifth_drv_poll(struct file *file, poll_table *wait)  
  118. {  
  119.     unsigned int mask = 0;  
  120.     poll_wait(file, &button_waitq, wait); // 不会立即休眠  
  121.   
  122.     if (ev_press)  
  123.         mask |= POLLIN | POLLRDNORM;  
  124.   
  125.     return mask;  
  126. }  
  127.   
  128. static int fifth_drv_fasync (int fd, struct file *filp, int on)  
  129. {  
  130.     printk("driver: fifth_drv_fasync\n");  
  131.     //初始化/释放 fasync_struct 结构体 (fasync_struct->fa_file->f_owner->pid)  
  132.     return fasync_helper (fd, filp, on, &button_async);  
  133. }  
  134.   
  135.   
  136. static struct file_operations sencod_drv_fops = {  
  137.     .owner   =  THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */  
  138.     .open    =  fifth_drv_open,       
  139.     .read    =  fifth_drv_read,      
  140.     .release =  fifth_drv_close,  
  141.     .poll    =  fifth_drv_poll,  
  142.     .fasync  =  fifth_drv_fasync,  
  143. };  
  144.   
  145.   
  146. int major;  
  147. static int fifth_drv_init(void)  
  148. {  
  149.     major = register_chrdev(0, "fifth_drv", &sencod_drv_fops);  
  150.   
  151.     fifthdrv_class = class_create(THIS_MODULE, "fifth_drv");  
  152.   
  153.     fifthdrv_class_dev = class_device_create(fifthdrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */  
  154.   
  155. //  gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);  
  156. //  gpfdat = gpfcon + 1;  
  157.   
  158.     return 0;  
  159. }  
  160.   
  161. static void fifth_drv_exit(void)  
  162. {  
  163.     unregister_chrdev(major, "fifth_drv");  
  164.     class_device_unregister(fifthdrv_class_dev);  
  165.     class_destroy(fifthdrv_class);  
  166. //  iounmap(gpfcon);  
  167.     return 0;  
  168. }  
  169.   
  170.   
  171. module_init(fifth_drv_init);  
  172.   
  173. module_exit(fifth_drv_exit);  
  174.   
  175. MODULE_LICENSE("GPL");  

 

 

http://blog.csdn.net/psvoldemort/article/details/21184525

以上是关于linux驱动的异步通知(kill_fasync,fasync)---- 驱动程序向应用程序发送信号的主要内容,如果未能解决你的问题,请参考以下文章

在Linux下的中断方式读取按键驱动程序

字符驱动程序之——异步信号通知

Linux驱动开发异步通知

Linux驱动开发异步通知

arm驱动linux异步通知与异步IO

:Linux设备驱动中的异步通知与同步I/O