Transferred from: http://blog.csdn.net/kingdragonfly120/article/details/10858647
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
When the Linux kernel space is interrupted, how to use the user-space application to run the corresponding function, when the chip has data to come when the kernel generates an interrupt, but how to notify the application to fetch data, this problem has been bothering me for a long time, and later found Linux has an asynchronous notification mechanism, in the user program to register a response to the Sigio signal callback function, and then in the driver to send a sigio signal to the process to complete the function, the following is the specific implementation method of the function:
1. Define a static struct fasync_struct *async in the driver;
2. Register Fasync_helper (FD, FILP, Mode, &async) in the Fasync system call;
3. Signal Kill_fasync (&async, SIGIO, poll_in) in Interrupt service procedure (top half, bottom half);
4. Register a callback function signal (SIGIO, Sig_handler) in the user application with signal in response to SIGIO;
5. Pass the process PID to the kernel via Fcntl (FD, F_setown, Getpid ())
6. Via Fcntl (FD, F_SETFL, Fcntl (FD, F_GETFL) | Fasync) Setting up asynchronous notifications
Drive part of the code:
[CPP]View PlainCopy
- #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; //Declaration 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); //Register upper call process information, upper call Fcntl set Fasync will call this system call
- }
- 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); //Send a sigio signal to the process that opened the device file
- 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);
User Application code:
[CPP]View PlainCopy
- #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)
- {
- }
- }
When an interrupt occurs in the kernel, a sigio signal is emitted in the interrupt service program to automatically invoke the corresponding callback function, which can be handled appropriately in the callback function.
The above program in the MINI2440 Development Board implemented by pressing the K1 key, the user program automatically calls the void Sig_handler (int sig) function
Linux kernel interrupt introduces user space (asynchronous notification mechanism) "go"