Home » Linux Kernel » Core Kernel » Implementation of Interrupt Handler (IRQ) in Linux kernel driver

Implementation of Interrupt Handler (IRQ) in Linux kernel driver

Following driver implements, how we can allocate an interrupt line using request_irq kernel API and how to implement an interrupt handler ( e.g. my_interrupt_handlerin this example ) and how to pass a structure with some values from module to IRQ handler.

This code is almost self explainatory with added comments inline. If you want to know ” What is the difference between setup_irq and request_irq in Linux kernel interrupts ” ?

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
// execute it as
// sudo insmod ./interrupt.ko interupt_name="some_name" irq=1
// for testing use irq numbers from cat /proc/interrupts
// remove module as
// sudo rmmod interrupt
static int irq;
static char *interrupt_name;
module_param(interrupt_name, charp,0);
MODULE_PARM_DESC(interrupt_name, "Name for the Interrupt");
module_param(irq, int, 0);
MODULE_PARM_DESC(irq, "The IRQ of the network interface");
struct info_to_pass {
    int *some_int;
    char *some_string;
static irqreturn_t my_interrupt_handler(int irq, void *dev_id) {
    static int mycount = 0;
    // info is what we passed as &dev_info to request_irq
    // this variable is just a argument carrier from module_init to IRQ handler.
    struct info_to_pass *info = dev_id;
    // static counter to just print debug message 10 times,
    // saying we received interrupt, after 10, we don't print anything
    // but interrupt might have came.
    if (mycount < 10) {
        printk("We received from module init : %s\n", info->some_string);
        printk("Interrupt! = %d\n", mycount);
    return IRQ_HANDLED;
static int __init mymodule_init(void) {
    printk ("My module initialised!\n");
/* request_irq: allocate a given interrupt line */
// int request_irq(unsigned int irq,
//                irq_handler_t handler,
//                unsigned long flags,
//                const char *name,
//                void *dev)
    dev_info.some_string = "helloworld";
    if (request_irq(irq, &my_interrupt_handler, IRQF_SHARED, interrupt_name, &dev_info)) {
        printk(KERN_ERR "myirqtest: cannot register IRQ %d\n", irq);
        return -EIO;
//The second parameter, handler, is a function pointer to the actual interrupt handler that services this interrupt. This function is invoked whenever the operating system receives the interrupt.
// IRQF_SHARED. This flag specifies that the interrupt line can be shared among multiple interrupt handlers. Each handler registered on a given line must specify this flag; otherwise, only one handler can exist per line.
    printk("Request on IRQ %d succeeded\n", irq);
    return 0;
static void __exit mymodule_exit(void) {
    free_irq(irq, &dev_info);
    printk("Freeing IRQ %d\n", irq);
    printk ("Unloading my module.\n");

The Simple makefile to compile this driver on Linux laptop is as follows,

obj-m += interrupt.o

        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Compile the driver as,

 $ make 
 $ sudo insmod ./interrupt.ko interrupt_name=somename irq=30 

Currently we have chosen random shared IRQ number 30 for testing to make sure we receive actual interrupt ( As in our driver, we dont consider real hardware interrupt with unique IRQ pin ) from /proc/interrupt

More Reference – https://notes.shichao.io/lkd/ch7/

Subscribe our Rurban Life YouTube Channel.. "Rural Life, Urban LifeStyle"

Leave a Comment