转自: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)设置异步通知

驱动部分代码:

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

用户应用程序代码:

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

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

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

Linux内核中断引入用户空间(异步通知机制)【转】的更多相关文章

  1. Linux 内核态与用户态通信 netlink

    参考资料: https://blog.csdn.net/zqixiao_09/article/details/77131283 https://www.cnblogs.com/lopnor/p/615 ...

  2. Linux 内核中断内幕

    转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html#resources Linux 内核中断内幕 ...

  3. 嵌入式Linux设备驱动程序:用户空间中的设备驱动程序

    嵌入式Linux设备驱动程序:用户空间中的设备驱动程序 Embedded Linux device drivers: Device drivers in user space Interfacing ...

  4. Linux内核中断顶半部和底半部的理解

    文章目录 中断上半部.下半部的概念 实现中断下半部的三种方法 软中断 软中断模版 tasklet tasklet函数模版 工作队列 工作队列函数模版 进程上下文和中断上下文 软中断和硬中断的区别 硬中 ...

  5. Linux内核中断和异常分析(中)

    在linux内核中,每一个能够发出中断请求的硬件设备控制器都有一条名为IRQ的输出线.所有现在存在的IRQ线都与一个名为可编程中断控制器的硬件电路的输入引脚相连,上次讲到单片机的时候,我就讲到了单片机 ...

  6. Linux之异步通知机制分析

    1.概念: 异步通知机制:一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,是一种“信号驱动的异步I/O”.信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号 ...

  7. linux内核态和用户态的信号量

    在Linux的内核态和用户态都有信号量,使用也不同,简单记录一下. 1> 内核信号量,由内核控制路径使用.内核信号量是struct semaphore类型的对象,它在中定义struct sema ...

  8. Linux内核态和用户态

    两张图说明Linux内核态和用户态之间的关系

  9. linux 设备驱动与应用程序异步通知

    一.异步通知机制简介 异步通知机制的意思:一旦设备准备就绪,可以主动的通知应用程序进行相应的操作,从而使得应用程序不必去查询设备的状态. 异步通知比较准确的称谓是"信号驱动的异步IO&quo ...

随机推荐

  1. C语言进阶——有符号与无符号02

    在计算机的内部,我们所有的信息都是由二进制数字组成的 有符号数的表实法: 在计算机内部用补码的方式表实有符号数 正数的补码位正数的本身 负数的补码为其绝对值取反然后加一得到 例如-7 他在计算机内部的 ...

  2. python-10多进程

    1-多进程(multiprocessing), 1个父进程可以有多少子进程 1.1下面的例子演示了启动一个子进程并等待其结束 from multiprocessing import Process i ...

  3. ISCSI网络存储

    ISCSI(iSCSI,Internet Small Computer System Interface) iSCSI技术实现了物理硬盘设备与TCP/IP网络协议的相互结合,使得用户可以通过互联网方便 ...

  4. Android 支付宝H5 没有回调

    今天测试反馈问题,说,手机上没有安装支付宝的,调用支付宝支付之后,没有回调.不提示成功也不提示失败. 我自己试了半天也都是没有问题 .后来终于可以试出来了. 发现原来是,清单里面注册的Activity ...

  5. URL地址传参中特殊符号的转码和解码

    背景: URL传参在web开发中很常见,一般来说这种方式并不推荐,原因就是浏览器多种多样,各家浏览器对URL地址的解析的表现很不一样,特别是当参数有非ASCII字符.英文字母.阿拉伯数字时. 在CRM ...

  6. 获取<考试>博文密码!o(*≧▽≦)ツ

    就是CJ高二组通用的密码 如果你想知道,请联系QQ,3057244225,或者直接面对面问博主(...) 是我们的内部材料,原创题目是不能外传的.请谅解. 当然如果是原题的话我们是不会上锁的啦

  7. 《Cracking the Coding Interview》——第8章:面向对象设计——题目10

    2014-04-24 00:05 题目:用拉链法设计一个哈希表. 解法:一个简单的哈希表,就看成一个数组就好了,每个元素是一个桶,用来放入元素.当有多个元素落入同一个桶的时候,就用链表把它们连起来.由 ...

  8. USACO Section1.5 Number Triangles 解题报告

    numtri解题报告 —— icedream61 博客园(转载请注明出处)--------------------------------------------------------------- ...

  9. USACO Section1.3 Mixing Milk 解题报告

    milk解题报告 —— icedream61 博客园(转载请注明出处)----------------------------------------------------------------- ...

  10. MySQL隐式转换测试

      Preface       There're various data type in MySQL such as number,string,date,time,lob,etc.The data ...