Linux内核中断引入用户空间(异步通知机制)
来源:互联网 发布:阿依莲正品淘宝折扣店 编辑:程序博客网 时间:2024/05/16 15:05
当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_structstruct 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)功能
阅读全文
1 0
- Linux内核中断引入用户空间(异步通知机制)
- Linux内核中断引入用户空间(异步通知机制)
- Linux内核中断引入用户空间(异步通知机制)
- Linux 内核空间与用户空间异步通信机制
- 内核和用户空间的消息传递-异步通知 (1)
- linux内核中异步通知机制--信号处理机制
- Linux内核异步通知
- Linux中断异步通知笔记
- linux 用户态和内核态以及进程上下文、中断上下文 内核空间用户空间理解
- linux内核--中断机制
- linux内核中断机制
- Linux驱动开发七:按键中断+poll机制+异步通知机制
- Linux驱动开发八:按键中断+poll机制+异步通知机制+信号量及阻塞标志
- Linux内核的异步通知
- linux 驱动异步通知机制
- 【Linux 驱动】异步通知机制
- linux中断和异步通知 基于QT210
- linux中断和异步通知 基于QT210
- RxJava使用场景小结
- 注册页面在安卓手机上调用输入法的时候背景上移问题
- 人造皮肤可以让机器人像我们一样感觉到
- 牛的旅行 Cow Tours
- 142_容器_重点总结
- Linux内核中断引入用户空间(异步通知机制)
- zepto.js 打包集成其他模块流程(如fx)
- 软件缺陷定义
- rsync + sersync + inotify-tools实现数据同步
- 过滤器与拦截器
- Hello World
- Android 实现音乐剪切功能 可以选择起始点和结束点 也可以同时拖动块级元素
- idea快捷键
- Java创建和解析Json数据方法(三)——json-lib包的使用