Here's a high-level view of the low-level processing. I'm describing a simple typical architecture, real architectures can be more complex or differ in ways that don't matter at this level of detail.

When an interrupt occurs, the processor looks if interrupts are masked. If they are, nothing happens until they are unmasked. When interrupts become unmasked, if there are any pending interrupts, the processor picks one.

Then the processor executes the interrupt by branching to a particular address in memory. The code at that address is called the interrupt handler. When the processor branches there, it masks interrupts (so the interrupt handler has exclusive control) and saves the contents of some registers in some place (typically other registers).

The interrupt handler does what it must do, typically by communicating with the peripheral that triggered the interrupt to send or receive data. If the interrupt was raised by the timer, the handler might trigger the OS scheduler, to switch to a different thread. When the handler finishes executing, it executes a special return-from-interrupt instruction that restores the saved registers and unmasks interrupts.

The interrupt handler must run quickly, because it's preventing any other interrupt from running. In the Linux kernel, interrupt processing is divided in two parts:

  • The “top half” is the interrupt handler. It does the minimum necessary, typically communicate with the hardware and set a flag somewhere in kernel memory.
  • The “bottom half” does any other necessary processing, for example copying data into process memory, updating kernel data structures, etc. It can take its time and even block waiting for some other part of the system since it runs with interrupts enabled.

As usual on this topic, for more information, read Linux Device Drivers; chapter 10 is about interrupts.

Answer from Gilles 'SO- stop being evil' on Stack Exchange
🌐
EmbeTronicX
embetronicx.com › tutorials › linux › device-drivers › linux-device-driver-tutorial-part-13-interrupt-example-program-in-linux-kernel
Interrupts Example Program in Linux Kernel – Linux Device Driver Tutorial - Part 13
September 24, 2023 - Most interrupt handlers do not set this flag, as disabling all interrupts is bad form. Its use is reserved for performance-sensitive interrupts that execute quickly. This flag is the current manifestation of the SA_INTERRUPT flag, which in the past distinguished between “fast” and “slow” interrupts. IRQF_SAMPLE_RANDOM: This flag specifies that interrupts generated by this device should contribute to the kernel entropy pool.
🌐
Linux Kernel Labs
linux-kernel-labs.github.io › refs › heads › master › lectures › interrupts.html
Interrupts — The Linux Kernel documentation
For example a network card generates an interrupts to signal that a packet has arrived. Most interrupts are maskable, which means we can temporarily postpone running the interrupt handler when we disable the interrupt until the time the interrupt is re-enabled.
Discussions

kernel - How is an Interrupt handled in Linux? - Unix & Linux Stack Exchange
In the Linux kernel, interrupt processing is divided in two parts: The “top half” is the interrupt handler. It does the minimum necessary, typically communicate with the hardware and set a flag somewhere in kernel memory. The “bottom half” does any other necessary processing, for example ... More on unix.stackexchange.com
🌐 unix.stackexchange.com
January 13, 2011
Linux - Interrupt Handling: Overview (Part 1)
Thanks for all the articles you wrote. Very interesting! More on reddit.com
🌐 r/linux
15
284
December 18, 2022
c - Kernel Module Programming ( Interrupt handler ) - Stack Overflow
I suggest you look for an unused interrupt for your learning project. 2017-09-17T05:57:50.167Z+00:00 ... @"Hai Dang" - as stated by @"Shachar Shemesh" once you used the free_irq of the keyboard IRQ you can't restore it and you must reboot your system. Please see the source of your code which explain this: linuxtopia.org/online_books/… 2018-12-12T07:28:24.23Z+00:00 ... You need to let the kernel know which handler ... More on stackoverflow.com
🌐 stackoverflow.com
Do interrupts actual interrupt or do they wait for a 'natural' context switch and jump the queue?
The short answer is that when an interrupt happens, the interrupt handler runs. A well-behaved interrupt handler saves CPU state, runs quickly without blocking, and then restores CPU state. This context switch happens whether or not the current thread is ultimately preempted. In modern OSes, the handler is divided into two parts : the part that quickly handles the actual interrupt, and the part that does the bulk of the work later. More on reddit.com
🌐 r/C_Programming
36
51
February 8, 2025
🌐
O'Reilly
oreilly.com › library › view › understanding-the-linux › 0596005652 › ch04s06.html
4.6. Interrupt Handling - Understanding the Linux Kernel, 3rd Edition [Book]
November 17, 2005 - An I/O device requires attention; the corresponding interrupt handler must query the device to determine the proper course of action. We cover this type of interrupt in the later section "I/O Interrupt Handling.” ... Some timer, either a local APIC timer or an external timer, has issued an interrupt; this kind of interrupt tells the kernel that a fixed-time interval has elapsed.
Authors   Daniel P. BovetMarco Cesati
Published   2005
Pages   942
🌐
The Linux Documentation Project
tldp.org › LDP › lkmpg › 2.6 › html › x1256.html
12.1. Interrupt Handlers
Then, when it receives a keyboard interrupt, it reads the keyboard's status (that's the purpose of the inb(0x64)) and the scan code, which is the value returned by the keyboard. Then, as soon as the kernel thinks it's feasible, it runs got_char which gives the code of the key used (the first seven bits of the scan code) and whether it has been pressed (if the 8th bit is zero) or released (if it's one). Example 12-1.
🌐
Linux Kernel
kernel.org › doc › html › v4.12 › core-api › genericirq.html
Linux generic IRQ handling — The Linux Kernel documentation
One example code path is as below: KVM -> IOMMU -> irq_set_vcpu_affinity(). ... Disable the selected interrupt line. Disables and Enables are nested. Unlike disable_irq(), this function does not ensure existing instances of the IRQ handler have completed before returning.
🌐
Opensource.com
opensource.com › article › 20 › 10 › linux-kernel-interrupts
How the Linux kernel handles interrupts | Opensource.com
October 5, 2020 - An abort invokes the system's abort exception handler, which terminates the process that caused it. IRQs are ordered by priority in a vector on the APIC (0=highest priority). The first 32 interrupts (0–31) have a fixed sequence that is specified by the CPU. You can find an overview of them on OsDev's Exceptions page. Subsequent IRQs can be assigned differently. The interrupt descriptor table (IDT) contains the assignment between IRQ and ISR. Linux defines an IRQ vector from 0 to 256 for the assignment.
Top answer
1 of 3
45

Here's a high-level view of the low-level processing. I'm describing a simple typical architecture, real architectures can be more complex or differ in ways that don't matter at this level of detail.

When an interrupt occurs, the processor looks if interrupts are masked. If they are, nothing happens until they are unmasked. When interrupts become unmasked, if there are any pending interrupts, the processor picks one.

Then the processor executes the interrupt by branching to a particular address in memory. The code at that address is called the interrupt handler. When the processor branches there, it masks interrupts (so the interrupt handler has exclusive control) and saves the contents of some registers in some place (typically other registers).

The interrupt handler does what it must do, typically by communicating with the peripheral that triggered the interrupt to send or receive data. If the interrupt was raised by the timer, the handler might trigger the OS scheduler, to switch to a different thread. When the handler finishes executing, it executes a special return-from-interrupt instruction that restores the saved registers and unmasks interrupts.

The interrupt handler must run quickly, because it's preventing any other interrupt from running. In the Linux kernel, interrupt processing is divided in two parts:

  • The “top half” is the interrupt handler. It does the minimum necessary, typically communicate with the hardware and set a flag somewhere in kernel memory.
  • The “bottom half” does any other necessary processing, for example copying data into process memory, updating kernel data structures, etc. It can take its time and even block waiting for some other part of the system since it runs with interrupts enabled.

As usual on this topic, for more information, read Linux Device Drivers; chapter 10 is about interrupts.

2 of 3
26

Gilles already described the general case of an interrupt, the following applies specifically to Linux 2.6 on an Intel architecture (part of this is also based on Intel's specifications).

An interrupt is an event that changes the sequence of instructions executed by the processor.
There are two different kinds of interrupts:

  • Synchronous interrupt (Exception) produced by the CPU while processing instructions
  • Asynchronous interrupt (Interrupt) issued by other hardware devices

Exceptions are caused by programming errors (f.e. Divide error, Page Fault, Overflow) that must be handled by the kernel. He sends a signal to the program and tries to recover from the error.

The following two exceptions are classified:

  • Processor-detected exception generated by the CPU while detecting a anomalous condition; divided into three groups: Faults can generally be corrected, Traps report an execution, Aborts are serious errors.
  • Programmed exception requested by the programmer, handled like a trap.

Interrupts can be issued by I/O devices (keyboard, network adapter, ..), interval timers and (on multiprocessor systems) other CPUs. When an interrupt occures, the CPU must stop his current instruction and execute the newly arrived interrupt. He needs to save the old interrupted process state to (probably) resume it after the interrupt is handled.

Handling interrupts is a sensitive task:

  • Interrupts can occur at any time, the kernel tries to get it out of the way as soon as possible
  • An interrupt can be interrupted by another interrupt
  • There are regions in the kernel which must not be interrupted at all

Two different interrupt levels are defined:

  • Maskable interrupts issued by I/O devices; can be in two states, masked or unmasked. Only unmasked interrupts are getting processed.
  • Nonmaskable interrupts; critical malfunctions (f.e. hardware failure); always processed by the CPU.

Every hardware device has it's own Interrupt Request (IRQ) line. The IRQs are numbered starting from 0. All IRQ lines are connected to a Programmable Interrupt Controller (PIC). The PIC listens on IRQs and assigns them to the CPU. It is also possible to disable a specific IRQ line.
Modern multiprocessing Linux systems generally include the newer Advanced PIC (APIC), which distributes IRQ requests equally between the CPUs.

The mid-step between an interrupt or exception and the handling of it is the Interrupt Descriptor Table (IDT). This table associates each interrupt or exception vector (a number) with a specified handler (f.e. Divide error gets handled by the function divide_error()).

Through the IDT, the kernel knows exactly how to handle the occurred interrupt or exception.


So, what does the kernel when an interrupt occurres?

  • The CPU checks after each instruction if there's a IRQ from the (A)PIC
  • If so, consults the IDT to map the received vector to a function
  • Checks if the interrupt was issued by a authorized source
  • Saves the registers of the interrupted process
  • Call the according function to handle the interrupt
  • Load the recently saved registers of the interrupted process and try to resume it
Find elsewhere
🌐
Linux Kernel Labs
linux-kernel-labs.github.io › refs › heads › master › labs › interrupts.html
I/O access and Interrupts — The Linux Kernel documentation
IRQF_ONESHOT interrupt will be reactivated after running the process context routine; Without this flag, the interrupt will be reactivated after running the handler routine in the context of the interrupt · Requesting the interrupt can be done either at the initialization of the driver (init_module()), when the device is probed, or when the device is used (e.g. during open). The following example performs the interrupt request for the COM1 serial port: #include <linux/interrupt.h> #define MY_BASEPORT 0x3F8 #define MY_IRQ 4 static my_init(void) { [...] struct my_device_data *my_data; int err; err = request_irq(MY_IRQ, my_handler, IRQF_SHARED, "com1", my_data); if (err < 0) { /* handle error*/ return err; } [...] }
🌐
GitHub
github.com › ANSANJAY › InterruptHandlinginKernel
GitHub - ANSANJAY/InterruptHandlinginKernel: A deep dive into the interrupt handling mechanisms within the Linux kernel. Explore how different devices, from keyboards to Ethernet ports, trigger and process interrupts. Complete with hands-on examples and real-world use cases. · GitHub
A deep dive into the interrupt handling mechanisms within the Linux kernel. Explore how different devices, from keyboards to Ethernet ports, trigger and process interrupts. Complete with hands-on examples and real-world use cases. - ANSANJAY/InterruptHandlinginKernel
Starred by 10 users
Forked by 2 users
Languages   C 91.5% | Makefile 8.5%
🌐
Baeldung
baeldung.com › home › processes › interrupt handling in linux
Interrupt Handling in Linux | Baeldung on Linux
March 19, 2025 - We can see in the previous image that there is yet another step between a device invoking an interrupt and its handling: the Interrupt Descriptor Table (IDT). In the IDT, there is an association between each interrupt and the ISR (interrupt handler) that the processor will call. The kernel knows, with the IDT, which interrupt handle will deal with each interrupt.
🌐
XML.com
xml.com › ldd › chapter › book › ch09.html
Linux Device Drivers, 2nd Edition: Chapter 9: Interrupt Handling
In fact, even if the modem had been used earlier but wasn't in use at the time of the snapshot, it would not show up in the file; the serial ports are well behaved and release their interrupt handlers when the device is closed. The /proc/interrupts display shows how many interrupts have been delivered to each CPU on the system. As you can see from the output, the Linux kernel tries to divide interrupt traffic evenly across the processors, with some success.
🌐
Reddit
reddit.com › r/linux › linux - interrupt handling: overview (part 1)
r/linux on Reddit: Linux - Interrupt Handling: Overview (Part 1)
December 18, 2022 -

After talking in general about the concept of interrupts (https://medium.com/@boutnaru/computer-architecture-interrupts-9d0dc849c1e5) now we are going to deep dive into how they are handled under Linux.

In order to handle an interrupt we first need to register it using a call to “request_irq” which adds the handler (https://elixir.bootlin.com/linux/v6.1/source/include/linux/interrupt.h#L165). In order to remove a handler we call “free_irq”. Fun fact, “request_irq” is referenced in 1280 files in the source code of the Linux kernel (version 6.1).

Overall, we can think about two major use cases when we are handling interrupts. First, interrupts that are designed to execute quickly. Second, interrupts which have to do several operations to complete (meaning they won’t execute quickly).

Due to that, interrupt handling has two phases (by the way it is true not only for Linux). We have “Top Half” and “Bottom Half”. The main reason for the split is the fact that we can’t perform large operations in interrupt-context (when interrupts are disable). So, what “Bottom Half” allows us is to defer work for later. For more information I suggest reading https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-9.html.

We can sum up the phases of a “Top Half” as follows: ensure that the interrupt was triggered by the correct hardware (in case of line sharing), clearing interrupt pending bit on the hardware (if needed), does everything that needs to be immediate (like reading/writing to/from the device) and schedule the “Bottom Half” (if needed). As an example we can see the interrupt handler for a floppy (https://elixir.bootlin.com/linux/v6.1/source/drivers/block/floppy.c#L1712) that calls the deferred work in the following line https://elixir.bootlin.com/linux/v6.1/source/drivers/block/floppy.c#L1765.

Thus, “Top Half” runs in an interrupt context, which is used for quick responses to external events and it is responsible for creating the deferred work for later (the “Bottom Half”) - as we can see in the timeline diagram shown below.

Lastly, We have three types for the category of “Bottom Half”: workques, tasklets and softirq (https://www.oreilly.com/library/view/understanding-the-linux/0596002130/ch04s07.html). We will dive into each one of them in future writeups. By the way, there are also timers and normal regular kernel threads that can be used for deferred work but they are less natural for interrupt handling so I won’t go over them in this series.

Next we are going to start diving into workques, tasklets and softirq. See you in the next writeup :-).

https://hugh712.gitbooks.io/embeddedsystem/content/Images/RealTime/RT006.png
🌐
EmbeTronicX
embetronicx.com › tutorials › linux › device-drivers › interrupts-in-linux-kernel
Interrupts in Linux Kernel - Linux Device Driver Tutorial Part 12
May 19, 2023 - The aim of this series is to provide easy and practical examples that anyone can understand. This is the Interrupts in Linux kernel driver – Linux Device Driver Tutorial Part 12. You can also read Sysfs, Procfs, Workqueue, Completion, Softirq, and threaded IRQ in the Linux device driver. ... This tutorial discusses the interrupts and how the kernel responds to them, with special functions called interrupt handlers ...
🌐
Google Sites
sites.google.com › site › knsathyawiki › example-page › chapter-7-interrupts-and-interrupt-handlers
Chapter 07. Interrupts and Interrupt Handlers - sathyablog
Processors can be orders of magnitudes faster than the hardware they talk to; it is not ideal for the kernel to issue a request and wait for a response from slower hardware. Instead, the kernel must be free to go and handle other work, dealing with the hardware only after that hardware has ...
🌐
O'Reilly
oreilly.com › library › view › linux-device-drivers › 0596005903 › ch10.html
10. Interrupt Handling - Linux Device Drivers, 3rd Edition [Book]
February 7, 2005 - 9.1. I/O Ports and I/O Memory9.1.1. I/O Registers and Conventional Memory9.2. Using I/O Ports9.2.1. I/O Port Allocation9.2.2. Manipulating I/O ports9.2.3. I/O Port Access from User Space9.2.4. String Operations9.2.5. Pausing I/O9.2.6. Platform Dependencies9.3. An I/O Port Example9.3.1. An Overview of the Parallel Port9.3.2. A Sample Driver9.4. Using I/O Memory9.4.1. I/O Memory Allocation and Mapping9.4.2. Accessing I/O Memory9.4.3. Ports as I/O Memory9.4.4. Reusing short for I/O Memory9.4.5. ISA Memory Below 1 MB9.4.6. isa_readb and Friends9.5. Quick Reference · 10.1. Preparing the Parallel Port10.2. Installing an Interrupt Handler10.2.1. The /proc Interface10.2.2. Autodetecting the IRQ Number10.2.2.1. Kernel-assisted probing10.2.2.2.
Authors   Jonathan CorbetAlessandro Rubini
Published   2005
Pages   636
🌐
Site24x7
site24x7.com › learn › linux › kernel-hardware-interrupts.html
What are hardware interrupts, and how do Linux kernels handle them: Site24x7
The interrupt handler in the kernel executes several ISRs. The ISR handles the request event (a hardware or software interrupt), then sends it to the CPU, pausing the active process. When the ISR is complete, the CPU will resume the process. Interrupt handling is the most complicated task controlled by the Linux ...
🌐
LinuxVox
linuxvox.com › blog › trigger-kernel-interrupt-handler-how
Kernel Interrupt Handlers in Linux: How & Who Triggers Them? + Defining/Modifying Hardware Handlers Explained — linuxvox.com
The CPU uses the Interrupt Descriptor Table (IDT)—a per-CPU table—to find the handler function for the interrupt. The IDT maps interrupt vectors (unique numbers) to kernel functions. ... Vectors 0–31 are reserved for exceptions (e.g., #DE for division by zero). Vectors 32+ map to hardware IRQs (e.g., IRQ 0 → vector 32). Linux routes the interrupt to the registered handler function (via the irq_desc structure, which tracks IRQ metadata).
🌐
Medium
medium.com › @boutnaru › linux-interrupt-handling-overview-part-1-bd0a841047d2
Linux — Interrupt Handling: Overview (Part 1) | by Shlomi Boutnaru, Ph.D. | Medium
December 17, 2022 - For more information I suggest reading https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-9.html. We can sum up the phases of a “Top Half” as follows: ensure that the interrupt was triggered by the correct hardware (in case of line sharing), clearing interrupt pending bit on the hardware (if needed), does everything that needs to be immediate (like reading/writing to/from the device) and schedule the “Bottom Half” (if needed). As an example we can see the interrupt handler for a floppy (https://elixir.bootlin.com/linux/v6.1/source/drivers/block/floppy.c#L1712) that calls the deferred work in the following line https://elixir.bootlin.com/linux/v6.1/source/drivers/block/floppy.c#L1765.
🌐
Linux Inside
0xax.gitbooks.io › linux-insides › content › Interrupts › linux-interrupts-1.html
Introduction · Linux Inside - 0xax
After this the interrupt handler begins to execute and when the interrupt handler finishes its execution, it must return control to the interrupted process with the iret instruction. The iret instruction unconditionally pops the stack pointer (ss:rsp) to restore the stack of the interrupted process and does not depend on the cpl change. That's all. It is the end of the first part of Interrupts and Interrupt Handling in the Linux kernel.