Skip to content

Instantly share code, notes, and snippets.

@carloscn
Created July 28, 2022 09:55
Show Gist options
  • Save carloscn/e7d00a4831f93bade45757d2a509ebef to your computer and use it in GitHub Desktop.
Save carloscn/e7d00a4831f93bade45757d2a509ebef to your computer and use it in GitHub Desktop.
Linux内核中断引入用户空间(异步通知机制)
#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)
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment