• Linux内核中断引入用户空间(异步通知机制)【转】


    转自:http://blog.csdn.net/kingdragonfly120/article/details/10858647

            当Linux内核空间发生中断后怎么使用户空间的应用程序运行相应的函数呢,当芯片有数据到来时内核会产生一个中断,但是怎样通知应用程序来取数据,以前这个问题一直困扰我很长时间,后来发现linux中有异步通知机制,在用户程序中用signal注册一个响应SIGIO信号的回调函数,然后在驱动程序中向该进程发出SIGIO信号便完成该功能,下面是该功能具体实施方法:

    1.在驱动中定义一个static struct fasync_struct *async;

    2.在fasync系统调用中注册fasync_helper(fd, filp, mode, &async);

    3.在中断服务程序(顶半部、底半部都可以)发出信号kill_fasync(&async, SIGIO, POLL_IN);

    4.在用户应用程序中用signal注册一个响应SIGIO的回调函数signal(SIGIO, sig_handler);

    5.通过fcntl(fd, F_SETOWN, getpid())将将进程pid传入内核

    6.通过fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | FASYNC)设置异步通知

     

    驱动部分代码:

     

     

    [cpp] view plain copy
     
    1. #include <linux/kernel.h>  
    2. #include <linux/errno.h>  
    3. #include <linux/module.h>  
    4. #include <linux/fs.h>  
    5. #include <linux/miscdevice.h>  
    6. #include <asm/io.h>  
    7. #include <linux/interrupt.h>  
    8. #include <linux/irq.h>  
    9. #include <linux/gpio.h>  
    10. #include <mach/regs-gpio.h>  
    11. #include <asm-generic/siginfo.h>  
    12. #include <linux/init.h>  
    13. #include <asm/signal.h>  
    14. #include <linux/timer.h>  
    15. #include <asm/uaccess.h>  
    16.   
    17. #define DEVICE_NAME "mybeep"  
    18.   
    19. volatile unsigned long *GPBCON;  
    20. volatile unsigned long *GPBDAT;  
    21. volatile unsigned long *GPBUP;  
    22. void beep_start(void);  
    23. void beep_stop(void);  
    24. int  beep_irq_register(void);  
    25. unsigned int flag=1;  
    26.   
    27. static struct fasync_struct *async; //声明fasync_struct  
    28. struct key_irq_desc {  
    29.     unsigned int irq;  
    30.     int pin;  
    31.     int pin_setting;  
    32.     int number;  
    33.     char *name;  
    34. };  
    35.   
    36. static int beep_fasync(int fd, struct file *filp, int mode)  
    37. {  
    38.     printk("application  fasync! ");  
    39.     return fasync_helper(fd, filp, mode, &async);         //注册上层调用进程的信息,上层调用fcntl设置FASYNC会调用这个系统调用  
    40. }  
    41.   
    42. static struct key_irq_desc key_irqs [] = {  
    43.     {IRQ_EINT8, S3C2410_GPG(0), S3C2410_GPG0_EINT8, 0, "KEY1"},  
    44. };  
    45.   
    46. static irqreturn_t key_interrupt(int irq, void *dev_id)  
    47. {  
    48.     kill_fasync(&async, SIGIO, POLL_IN);  //向打开设备文件的进程发出SIGIO信号  
    49.     return (IRQ_HANDLED);  
    50. }  
    51.   
    52. void beep_gpiob_init(void)  
    53. {  
    54.     *GPBCON&=~((1<<0)|(1<<1));  
    55.     *GPBCON|=(1<<0);  
    56.     *GPBUP&=~(1<<0);  
    57. }  
    58.   
    59. void beep_start(void)  
    60. {  
    61.     *GPBDAT|=(1<<0);  
    62. }  
    63.   
    64. void beep_stop(void)  
    65. {  
    66.     *GPBDAT&=~(1<<0);  
    67. }  
    68.   
    69. int beep_open(struct inode *inode, struct file *filp)  
    70. {  
    71.     if(beep_irq_register() != 0)  
    72.     {  
    73.         printk("Request irq error! ");  
    74.     }  
    75.     printk(KERN_ALERT "application  open! ");  
    76.     return 0;  
    77. }  
    78.   
    79. ssize_t beep_read(struct file *file, char __user *buff, size_t count, loff_t *offp)  
    80. {  
    81.     printk("application  read! ");  
    82.     return 0;  
    83. }  
    84.   
    85. ssize_t beep_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)  
    86. {  
    87.     printk("application  write! ");  
    88.     return 0;  
    89. }  
    90.   
    91. static int beep_release(struct inode *inode, struct file *file)  
    92. {  
    93.     disable_irq(key_irqs[0].irq);  
    94.     free_irq(key_irqs[0].irq, (void *)&key_irqs[0]);  
    95.     printk("application  close! ");  
    96.     return beep_fasync(-1, file, 0);  
    97. }  
    98.   
    99. static int beep_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)  
    100. {  
    101.     switch(cmd)  
    102.     {  
    103.     case 0:  
    104.         beep_start();  
    105.         break;  
    106.     case 1:  
    107.         beep_stop();  
    108.         break;  
    109.     default:  
    110.         break;  
    111.     }  
    112.     return 0;  
    113. }  
    114.   
    115. static struct file_operations beep_ops = {  
    116.     .owner = THIS_MODULE,  
    117.     .open = beep_open,  
    118.     .release = beep_release,  
    119.     .ioctl = beep_ioctl,  
    120.     .read = beep_read,  
    121.     .write = beep_write,  
    122.     .fasync = beep_fasync,  
    123. };  
    124.   
    125. static struct miscdevice beep_misc = {  
    126.     .minor = MISC_DYNAMIC_MINOR,  
    127.     .name = DEVICE_NAME,  
    128.     .fops = &beep_ops,  
    129. };  
    130.   
    131. int beep_irq_register(void)  
    132. {  
    133.     int err;  
    134.     err = request_irq(key_irqs[0].irq, key_interrupt, 0, key_irqs[0].name, (void *)&key_irqs[0]);  
    135.     set_irq_type(key_irqs[0].irq, IRQ_TYPE_EDGE_RISING);  
    136.     if(err)  
    137.     {  
    138.         disable_irq(key_irqs[0].irq);  
    139.         free_irq(key_irqs[0].irq, (void *)&key_irqs[0]);  
    140.         return -EBUSY;  
    141.     }  
    142.     return 0;  
    143. }  
    144.   
    145. static int __init beep_init(void)  
    146. {  
    147.     int ret;  
    148.     ret=misc_register(&beep_misc);  
    149.     if(ret <0)  
    150.     {  
    151.         printk("register miscdevice error code:%d ",ret);  
    152.         return ret;  
    153.     }  
    154.     printk("beep device create! ");  
    155.     GPBCON=(volatile unsigned long *)ioremap(0x56000010,12);  
    156.     GPBDAT=GPBCON+1;  
    157.     GPBUP=GPBCON+2;  
    158.     beep_gpiob_init();  
    159.     return 0;  
    160. }  
    161.   
    162. static void __exit beep_exit(void)  
    163. {  
    164.     iounmap(GPBCON);  
    165.     misc_deregister(&beep_misc);  
    166.     printk("beep device delete! ");  
    167. }  
    168.   
    169. MODULE_LICENSE("GPL");  
    170. MODULE_AUTHOR("kingdragonfly");  
    171. module_init(beep_init);  
    172. module_exit(beep_exit);  


    用户应用程序代码:

     

    [cpp] view plain copy
     
    1. #include <stdio.h>  
    2. #include <unistd.h>  
    3. #include <signal.h>  
    4. #include <fcntl.h>  
    5.   
    6. void sig_handler(int sig)  
    7. {  
    8.     if(sig == SIGIO)  
    9.     {  
    10.         printf("Receive io signal from kernel! ");  
    11.     }  
    12. }  
    13.   
    14. int main(void)  
    15. {  
    16.     int fd;  
    17.     signal(SIGIO, sig_handler);  
    18.     fd = open("/dev/mybeep",O_RDWR);  
    19.     fcntl(fd, F_SETOWN, getpid());  
    20.     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | FASYNC);  
    21.     printf("waiting key interrupt: ");  
    22.     while(1)  
    23.     {  
    24.     }  
    25. }  

    当内核里发生中断时在中断服务程序中发出SIGIO信号从而自动调用相应的回调函数,在回调函数中可以进行相应处理。

    上面程序在mini2440开发板实现了按K1键,用户程序自动调用void sig_handler(int sig)功能

  • 相关阅读:
    3709: [PA2014]Bohater
    T89379 【qbxt】复读警告
    T89353 【BIO】RGB三角形
    T89359 扫雷
    P1325 雷达安装
    P2983 [USACO10FEB]购买巧克力
    DP----鬼畜的数字三角形
    提高组突破嘤
    数据结构题目大赏 (一堆题目没做)
    DAY 3
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/7074462.html
Copyright © 2020-2023  润新知