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)设置异步通知
驱动部分代码:
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/miscdevice.h>
- #include <asm/io.h>
- #include <linux/interrupt.h>
- #include <linux/irq.h>
- #include <linux/gpio.h>
- #include <mach/regs-gpio.h>
- #include <asm-generic/siginfo.h>
- #include <linux/init.h>
- #include <asm/signal.h>
- #include <linux/timer.h>
- #include <asm/uaccess.h>
- #define DEVICE_NAME "mybeep"
- volatile unsigned long *GPBCON;
- volatile unsigned long *GPBDAT;
- volatile unsigned long *GPBUP;
- void beep_start(void);
- void beep_stop(void);
- int beep_irq_register(void);
- unsigned int flag=1;
- static struct fasync_struct *async; //声明fasync_struct
- struct key_irq_desc {
- unsigned int irq;
- int pin;
- int pin_setting;
- int number;
- char *name;
- };
- static int beep_fasync(int fd, struct file *filp, int mode)
- {
- printk("application fasync!\n");
- return fasync_helper(fd, filp, mode, &async); //注册上层调用进程的信息,上层调用fcntl设置FASYNC会调用这个系统调用
- }
- static struct key_irq_desc key_irqs [] = {
- {IRQ_EINT8, S3C2410_GPG(0), S3C2410_GPG0_EINT8, 0, "KEY1"},
- };
- static irqreturn_t key_interrupt(int irq, void *dev_id)
- {
- kill_fasync(&async, SIGIO, POLL_IN); //向打开设备文件的进程发出SIGIO信号
- return (IRQ_HANDLED);
- }
- void beep_gpiob_init(void)
- {
- *GPBCON&=~((1<<0)|(1<<1));
- *GPBCON|=(1<<0);
- *GPBUP&=~(1<<0);
- }
- void beep_start(void)
- {
- *GPBDAT|=(1<<0);
- }
- void beep_stop(void)
- {
- *GPBDAT&=~(1<<0);
- }
- int beep_open(struct inode *inode, struct file *filp)
- {
- if(beep_irq_register() != 0)
- {
- printk("Request irq error!\n");
- }
- printk(KERN_ALERT "application open!\n");
- return 0;
- }
- ssize_t beep_read(struct file *file, char __user *buff, size_t count, loff_t *offp)
- {
- printk("application read!\n");
- return 0;
- }
- ssize_t beep_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)
- {
- printk("application write!\n");
- return 0;
- }
- static int beep_release(struct inode *inode, struct file *file)
- {
- disable_irq(key_irqs[0].irq);
- free_irq(key_irqs[0].irq, (void *)&key_irqs[0]);
- printk("application close!\n");
- return beep_fasync(-1, file, 0);
- }
- static int beep_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- {
- switch(cmd)
- {
- case 0:
- beep_start();
- break;
- case 1:
- beep_stop();
- break;
- default:
- break;
- }
- return 0;
- }
- static struct file_operations beep_ops = {
- .owner = THIS_MODULE,
- .open = beep_open,
- .release = beep_release,
- .ioctl = beep_ioctl,
- .read = beep_read,
- .write = beep_write,
- .fasync = beep_fasync,
- };
- static struct miscdevice beep_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &beep_ops,
- };
- int beep_irq_register(void)
- {
- int err;
- err = request_irq(key_irqs[0].irq, key_interrupt, 0, key_irqs[0].name, (void *)&key_irqs[0]);
- set_irq_type(key_irqs[0].irq, IRQ_TYPE_EDGE_RISING);
- if(err)
- {
- disable_irq(key_irqs[0].irq);
- free_irq(key_irqs[0].irq, (void *)&key_irqs[0]);
- return -EBUSY;
- }
- return 0;
- }
- static int __init beep_init(void)
- {
- int ret;
- ret=misc_register(&beep_misc);
- if(ret <0)
- {
- printk("register miscdevice error code:%d\n",ret);
- return ret;
- }
- printk("beep device create!\n");
- GPBCON=(volatile unsigned long *)ioremap(0x56000010,12);
- GPBDAT=GPBCON+1;
- GPBUP=GPBCON+2;
- beep_gpiob_init();
- return 0;
- }
- static void __exit beep_exit(void)
- {
- iounmap(GPBCON);
- misc_deregister(&beep_misc);
- printk("beep device delete!\n");
- }
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("kingdragonfly");
- module_init(beep_init);
- module_exit(beep_exit);
用户应用程序代码:
- #include <stdio.h>
- #include <unistd.h>
- #include <signal.h>
- #include <fcntl.h>
- void sig_handler(int sig)
- {
- if(sig == SIGIO)
- {
- printf("Receive io signal from kernel!\n");
- }
- }
- int main(void)
- {
- int fd;
- signal(SIGIO, sig_handler);
- fd = open("/dev/mybeep",O_RDWR);
- fcntl(fd, F_SETOWN, getpid());
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | FASYNC);
- printf("waiting key interrupt:\n");
- while(1)
- {
- }
- }
当内核里发生中断时在中断服务程序中发出SIGIO信号从而自动调用相应的回调函数,在回调函数中可以进行相应处理。
上面程序在mini2440开发板实现了按K1键,用户程序自动调用void sig_handler(int sig)功能
Linux内核中断引入用户空间(异步通知机制)【转】的更多相关文章
- Linux 内核态与用户态通信 netlink
参考资料: https://blog.csdn.net/zqixiao_09/article/details/77131283 https://www.cnblogs.com/lopnor/p/615 ...
- Linux 内核中断内幕
转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html#resources Linux 内核中断内幕 ...
- 嵌入式Linux设备驱动程序:用户空间中的设备驱动程序
嵌入式Linux设备驱动程序:用户空间中的设备驱动程序 Embedded Linux device drivers: Device drivers in user space Interfacing ...
- Linux内核中断顶半部和底半部的理解
文章目录 中断上半部.下半部的概念 实现中断下半部的三种方法 软中断 软中断模版 tasklet tasklet函数模版 工作队列 工作队列函数模版 进程上下文和中断上下文 软中断和硬中断的区别 硬中 ...
- Linux内核中断和异常分析(中)
在linux内核中,每一个能够发出中断请求的硬件设备控制器都有一条名为IRQ的输出线.所有现在存在的IRQ线都与一个名为可编程中断控制器的硬件电路的输入引脚相连,上次讲到单片机的时候,我就讲到了单片机 ...
- Linux之异步通知机制分析
1.概念: 异步通知机制:一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,是一种“信号驱动的异步I/O”.信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号 ...
- linux内核态和用户态的信号量
在Linux的内核态和用户态都有信号量,使用也不同,简单记录一下. 1> 内核信号量,由内核控制路径使用.内核信号量是struct semaphore类型的对象,它在中定义struct sema ...
- Linux内核态和用户态
两张图说明Linux内核态和用户态之间的关系
- linux 设备驱动与应用程序异步通知
一.异步通知机制简介 异步通知机制的意思:一旦设备准备就绪,可以主动的通知应用程序进行相应的操作,从而使得应用程序不必去查询设备的状态. 异步通知比较准确的称谓是"信号驱动的异步IO&quo ...
随机推荐
- HDU 5446 Unknown Treasure (卢卡斯+CRT
代码: #include"bits/stdc++.h" #define db double #define ll long long #define vec vector<l ...
- Git ---游离状态下的commit 分支切换与找回,commit之后无法找到历史记录
commit之后无法找到历史记录 https://blog.csdn.net/zyb2017/article/details/78307688
- POJ-3126 BFS,埃式筛选及黑科技
题目大意:给定两个四位素数a b,要求把a变换到b,变换的过程要保证 每次变换出来的数都是一个 四位素数,而且当前这步的变换所得的素数 与 前一步得到的素数 只能有一个位不同,而且每步得到的 ...
- 使用MD5比较两个文件是否相同
MD5算法:是计算机广泛使用的一种哈希算法,将数据(如汉字)运算为另一固定长度值,用于确保信息传输完整一致.java,C++ 等多种编程语言都有MD5的实现,可直接使用. 文件MD5值:每个文件都可以 ...
- Java线程和多线程(五)——单例类中的线程安全
单例模式是最广泛使用的创建模式之一.在现实世界之中,诸如Databae的连接或者是企业信息系统(EIS)等,通常其创建都是受到限制的,应该尽量复用已存在对象而不是频繁创建销毁.为了达到这个目的,开发者 ...
- The GNU C Library
Any Unix-like operating system needs a C library: the library which defines the ``system calls'' and ...
- PL/SQL 循环语句
1.基本 LOOP 循环语句 语法: LOOP 语句序列; END LOOP; 其中,语句序列中需要一个EXIT语句或一个EXIT WHEN语句来中断循环. 实例: DECLARE x ) :; BE ...
- shell文本处理工具总结
shell文本处理工具总结 为了效率,应该熟练的掌握自动化处理相关的知识和技能,能力就表现在做同样的一件事情,可以做的很好的同时,耗时还很短. 再次总结shell文本处理的相关规则,对提高软件调试效率 ...
- FTP数字代码的意义
110 重新启动标记应答.120 服务在多久时间内ready.125 数据链路端口开启,准备传送.150 文件状态正常,开启数据连接端口.200 命令执行成功.202 命令执行失败.211 系统状态或 ...
- java案例1,打印hello java
package anli1; public class hellojava { public static void main(String []args){ System.out.println(& ...