Linux Interrupt Requests (IRQs): Concepts, Inspection, and Common IRQs
Learn how hardware interrupts and IRQs work in Linux, review traditional x86 IRQ assignments, and inspect interrupt activity with /proc/interrupts.
An interrupt is a signal that tells a processor that something requires attention. Instead of waiting for the currently running program to finish, the processor can briefly handle the event and then resume its previous work.
An IRQ, short for interrupt request, traditionally means a numbered hardware interrupt request line. In modern Linux, the word also commonly refers to a kernel-visible interrupt identifier. The modern identifier may not match an old physical IRQ line.
How an interrupt works
Normal program execution is mostly sequential: the processor fetches instructions, executes them, and continues to the next instructions. Hardware events are different. A network packet, key press, completed disk operation, or timer event can occur at any time while a program is running.
- A device detects an event, such as received data or a completed transfer.
- The device signals an interrupt through an interrupt line or a message-signaled mechanism.
- An interrupt controller receives, prioritizes, and routes the request to a processor.
- The processor pauses the interrupted execution context and enters kernel interrupt handling.
- The kernel runs the registered interrupt handler, which acknowledges the event and performs the urgent device-specific work.
- The processor returns to the interrupted code or continues other scheduled kernel work.
An interrupt handler is kernel code registered for a particular interrupt source. It normally does only the time-sensitive portion of the work. More extensive processing can be deferred so that the processor returns quickly to normal execution.
Why devices use interrupts
Without interrupts, software could use polling: repeatedly checking a device to ask whether it has work. Polling is simple, but it consumes processor time even when nothing has happened. Interrupts let the processor do useful work and respond when the device actually needs service.
- Keyboard input: a key press produces input that must be delivered to the operating system.
- Mouse and USB activity: USB controllers report transfers and input events. A USB keyboard may therefore appear through a USB controller interrupt rather than a dedicated historical keyboard IRQ.
- Storage completion: a disk or SSD can interrupt when a requested read or write has completed.
- Network packets: a network controller can interrupt when packets arrive or transmit queues need service.
- Timers: periodic timer interrupts support scheduling and timekeeping.
- Real-time clock events: the RTC can generate alarms or periodic events.
- Serial communication: a serial controller can notify the kernel that data arrived or that its transmit buffer needs attention.
Interrupts do not eliminate all polling. Drivers may use polling in particular modes, during recovery, or when very high event rates make constant interrupts inefficient. Devices can also combine interrupts with DMA, where the device transfers data directly to memory and interrupts the kernel after a batch is ready.
Traditional x86 IRQ numbering
Early IBM-compatible x86 PCs commonly used two cascaded PICs, or Programmable Interrupt Controllers. This design provided the familiar legacy IRQ numbers 0 through 15. The second controller was connected through IRQ 2 on the first controller, which is why IRQ 2 is described as the cascade connection.
The following table is a historical reference for that layout. It is useful for understanding older hardware and documentation, but it is not a complete description of interrupt handling on a current Linux computer.
| Legacy IRQ number | Traditional common purpose | Historical device examples | Modern applicability and notes |
|---|---|---|---|
| 0 | System timer | Programmable interval timer | A legacy timer assignment; modern systems also use local APIC timers and other clock sources. |
| 1 | Keyboard controller | Traditional PC keyboard | USB input normally uses a USB controller and its assigned interrupt instead. |
| 2 | Cascade connection | Connection from the master PIC to the slave PIC | Reserved by the dual-PIC design; it is not normally a general device assignment. |
| 3 | Serial communications | Commonly COM2 | A conventional legacy serial assignment; hardware and firmware can differ. |
| 4 | Serial communications | Commonly COM1 | Often associated with another legacy serial port. |
| 5 | Expansion or parallel-port related | Often a secondary parallel port or an expansion card | Historically flexible and frequently unused on systems without the corresponding hardware. |
| 6 | Floppy disk controller | Floppy disk drive controller | Usually unused on modern systems without floppy hardware. |
| 7 | Parallel port or expansion device | Commonly LPT1 or an expansion card | Often unused on modern systems; the assignment was not universal. |
| 8 | Real-time clock | RTC periodic or alarm functions | A traditional RTC assignment; contemporary RTC devices may be represented differently by the kernel. |
| 9 | Peripheral or redirected legacy interrupt | Historically available for expansion; sometimes associated with ACPI-related routing | Firmware and operating-system routing commonly determine the actual use. |
| 10 | Expansion device | Peripheral or adapter | Historically available and commonly shared or reassigned. |
| 11 | Expansion device | Peripheral or adapter | Historically available and commonly shared or reassigned. |
| 12 | PS/2 mouse | Traditional PS/2 mouse controller | USB mice use USB-controller interrupts; IRQ 12 is not a universal modern mouse assignment. |
| 13 | Floating-point unit | Math coprocessor | A historical PC convention, generally not a normal device IRQ on current x86 systems. |
| 14 | Primary IDE controller | Primary ATA channel | Modern SATA and NVMe devices use contemporary controller and interrupt mechanisms. |
| 15 | Secondary IDE controller | Secondary ATA channel | Usually relevant only to older IDE-based systems. |
Several entries in the table were conventional rather than guaranteed. Some were reserved by the controller design, some were commonly unused, and others could be assigned to expansion hardware. IRQ sharing and firmware or kernel routing also caused real systems to differ from the textbook list.
Modern Linux interrupt architecture
PIC, APIC, and interrupt controllers
A PIC is the legacy x86 interrupt-controller design associated with the 0–15 layout. Contemporary x86 systems generally use the APIC, or Advanced Programmable Interrupt Controller, architecture.
An APIC system commonly includes an I/O APIC, which receives external device interrupts and routes them to processor cores, and a local APIC in each CPU. Local APICs handle local timer interrupts and interprocessor interrupts, among other functions. An interprocessor interrupt lets one CPU signal another CPU for tasks such as scheduling or coordinating kernel work.
x86-64 computers and other current platforms commonly expose more interrupt vectors or Linux IRQ entries than the 16 legacy lines. Linux's displayed IRQ number is a kernel-visible mapping selected through the platform's interrupt controllers and device configuration. It does not necessarily identify an old ISA wire.
PCI, PCIe, INTx, MSI, and MSI-X
PCI and PCI Express devices can use several interrupt-delivery methods:
| Method | Signal mechanism | Can be shared | Typical context |
|---|---|---|---|
| Legacy ISA/PIC line interrupts | A device asserts one of the traditional physical interrupt lines. | Some lines may be shared or routed through the legacy controller. | Older PC hardware and compatibility paths. |
| PCI INTx | A PCI device signals through a pin-based interrupt request. | Yes; sharing is a normal part of the line-based design. | Older PCI devices and compatibility configurations. |
| MSI | The device writes a specially defined message to signal an interrupt. | Usually avoids the traditional shared physical line model. | Many PCI and PCIe devices. |
| MSI-X | An extended message-signaled mechanism with multiple independently configurable interrupt vectors. | Typically provides separate messages for queues or functions. | High-performance network, storage, and other multiqueue devices. |
With MSI and MSI-X, a device signals by writing an interrupt message rather than asserting a physical IRQ line. A network card might have a separate interrupt for each receive or transmit queue. This is why a modern device can produce several Linux interrupt entries and why its number may be far outside the historical 0–15 range.
Inspecting interrupts with procfs
procfs is a virtual filesystem provided by the kernel. It does not represent ordinary files stored permanently on disk. Instead, paths under /proc present current process and kernel information. For background, see File Structure in Linux.
The primary interface for basic interrupt inspection is /proc/interrupts. Read it with:
cat /proc/interrupts
It is usually readable by an unprivileged user. A typical listing has CPU headings, one or more numeric counters, an interrupt identifier, a controller or vector description, and labels identifying the registered source.
| Field or column | Meaning | Example interpretation |
|---|---|---|
| CPU headings | One column for each CPU that can be shown by the kernel. | Counts under CPU0 and CPU1 show how many times that source was handled on each CPU. |
| Interrupt identifier | The Linux-visible IRQ number or a named special interrupt category. | A number such as 42 is a kernel mapping, not necessarily legacy IRQ 42 hardware. |
| Interrupt-controller or vector description | Text describing the interrupt controller, delivery path, or vector category. | The wording depends on architecture and kernel version. |
| Per-CPU cumulative count | The number of handled interrupts attributed to each CPU since the counters began or were reset. | A rapidly increasing value indicates ongoing interrupt activity. |
| Device, queue, or driver label | The registered interrupt handler or source associated with the row. | A network-driver or queue label can identify which interface or queue owns the activity. |
The trailing labels are especially useful, but they are not guaranteed to be simple device names. A label can identify a driver, a network queue, a USB controller, a storage controller, or another registered interrupt source. Multiple labels on one row commonly indicate shared interrupt handling.
Watching interrupt activity
A single snapshot tells you what has accumulated, not what is happening now. Refresh the listing once per second:
watch -n 1 'cat /proc/interrupts'
While it refreshes, try an action such as moving a mouse, pressing keys, generating network traffic, or performing disk I/O. The rows that change depend on the hardware, driver, power state, and interrupt mode. USB keyboard and mouse activity may increment a USB-controller row rather than a row named keyboard or mouse.
You can filter for likely network or storage labels:
grep -Ei 'eth|enp|ens|wlan|nvme|ahci|virtio' /proc/interrupts
Modern multiqueue devices may have several matching rows. Exact labels vary by driver and platform.
For a two-sample comparison, save the output, wait, and compare it:
cat /proc/interrupts > /tmp/interrupts.before
sleep 5
cat /proc/interrupts > /tmp/interrupts.after
diff -u /tmp/interrupts.before /tmp/interrupts.after
Counter changes are generally more informative than a static sample. The temporary files use /tmp; choose another writable location if local system policy requires it.
Interpreting counts and special entries
A rising counter means that the kernel is servicing that interrupt source. If a network transfer causes the counters for a network device's queues to increase, that is evidence that the device is generating interrupts and the associated handlers are running.
A zero or unchanged counter is not automatically an error. An idle device should not generate many interrupts. A device may also be using polling, may be represented by a shared controller row, or may not have generated an event during the observation period.
- Local timer interrupts: generated by per-CPU timers and expected to increase during normal operation.
- Interprocessor interrupts: CPU-to-CPU signals used for coordination and kernel activity.
- Error counters: categories that record certain interrupt-controller or platform errors when supported.
- Spurious interrupts: unexpected interrupt reports for which no valid source is identified or which the platform classifies as spurious.
The exact names and categories differ by architecture and kernel version. A nonzero special counter is a clue for further investigation, not proof of a hardware fault. Pay attention to its rate of increase and correlate it with kernel logs, workload, firmware, and device state.
IRQ sharing, affinity, and performance
IRQ sharing
IRQ sharing means that multiple devices or handlers use one interrupt source. It is particularly common with legacy line-based interrupts and PCI INTx. When a shared interrupt arrives, the kernel checks the registered handlers to determine which device needs service.
MSI and MSI-X frequently reduce the need for shared lines. MSI-X can provide multiple vectors, allowing a high-throughput device to associate different interrupt sources with different queues or functions. This does not mean every modern device has a unique single interrupt; configuration remains driver- and platform-dependent.
IRQ affinity
IRQ affinity is the set of CPUs permitted to process a particular interrupt. Read the affinity list for an IRQ shown in /proc/interrupts:
cat /proc/irq/<IRQ_NUMBER>/smp_affinity_list
Replace <IRQ_NUMBER> with the numeric identifier. The interface may be absent or restricted because of the kernel configuration, architecture, container environment, or permissions.
Distributing high-rate network or storage interrupts across suitable CPUs can improve throughput and reduce latency. Conversely, placing interrupts on an isolated, overloaded, or latency-sensitive CPU can hurt performance. Uneven counts are not automatically a problem: queue affinity, virtual machines, CPU isolation, and workload placement can all make the distribution intentional.
The same interface can be used for configuration on systems that permit it. Writing an affinity value changes the CPUs eligible to handle the IRQ, generally requires elevated privileges, and can harm responsiveness or throughput if chosen incorrectly. Treat this as controlled performance tuning, not a routine repair command.
irqbalance is a service available on many distributions that automatically distributes eligible interrupts across CPUs. Its installation, enabled state, policy, and interaction with manually configured affinity are distribution- and workload-specific. Check the current policy before enabling, disabling, or overriding it.
Safe diagnostic method
- Observe first. Capture
/proc/interruptsbefore and during the device activity. - Identify the source. Use the device, driver, interface, or queue labels rather than relying only on the numeric IRQ.
- Check the route. Determine whether the device uses a shared line, MSI, or MSI-X when that information is available from platform and driver tools.
- Compare related evidence. Inspect kernel messages, driver status, firmware information, power-management state, cables, and device errors separately.
- Change settings only with a reason. Record the original affinity and have a recovery plan before making tuning changes.
Modern interrupt routing is largely managed by firmware, hardware, and the kernel. Do not force an old legacy IRQ value onto a PCIe device merely because its number differs from a 0–15 reference table. Such a change may be ignored, break routing, or create a more difficult recovery problem.
Interrupt behavior can resemble other failures. A device that appears inactive may have a driver problem, a disconnected cable, a firmware issue, a power-management transition, a failed device, or a problem above the interrupt layer. Likewise, a changing counter proves that an interrupt is being serviced, but it does not prove that the device is functioning correctly.
Troubleshooting examples
A keyboard, mouse, network interface, or storage device appears inactive
- Capture
/proc/interruptsbefore and during the relevant action. - Check whether a likely device or controller row changes.
- Inspect kernel messages and device-driver status independently.
No counter change can suggest a device, connection, driver, firmware, or power-management issue. However, the device may be represented by an unexpected controller or shared interrupt entry, so absence of an obvious label is not conclusive.
One CPU handles much more interrupt activity than the others
- Identify high-rate rows in
/proc/interrupts. - Read the relevant
smp_affinity_listfile. - Determine whether irqbalance is running and whether the workload intentionally pins queues or CPUs.
Uneven counts may be expected. Investigate performance impact, latency, and workload placement before changing affinity.
A device uses an unexpected IRQ number
Check the device label, determine whether it uses PCIe MSI or MSI-X, and remember that modern Linux IRQ numbering is not limited to 0 through 15. An unfamiliar number is normally expected on APIC- and MSI-capable systems.
Several device labels appear on one row
This usually indicates a shared line-based interrupt. Compare the row while using each device, then consult driver and hardware documentation before attempting any routing change.
Error or spurious counters rise
- Record the counters and their rate of increase.
- Review kernel logs, firmware versions, driver versions, and hardware connections.
- Correlate the increase with a device workload or power-state transition.
Persistent increases deserve platform-specific investigation, but an isolated nonzero value does not establish a fault by itself.
Exam-relevant summary
- An interrupt is a signal requiring processor attention; an IRQ traditionally identifies a hardware request line.
- The basic path is device event, interrupt controller, CPU, kernel handler, device service, and resumed work.
- Legacy x86 PCs used IRQ numbers 0 through 15 with dual PIC hardware.
- Modern Linux commonly uses APIC-based routing and PCI or PCIe MSI/MSI-X, so Linux IRQ identifiers can exceed 15.
/proc/interruptsshows cumulative per-CPU counts and registered source labels.- Changing counts show activity, but unchanged counts can be normal for idle devices.
- IRQ sharing is normal for some line-based configurations; MSI-X often supplies multiple vectors for multiqueue devices.
- IRQ affinity controls which CPUs may handle an interrupt, and irqbalance may manage that distribution automatically.
- Observe before changing interrupt settings, and do not apply legacy IRQ assumptions to modern PCIe hardware.
For related command-line practice, see Show The Full Path Of Shell Commands and Bourne Again Shell Bash.