You know that feeling when you're deep in something and suddenly your phone buzzes, and your brain just drops everything to check it? Worth adding: that's basically what happens inside your computer a few million times per second. Except instead of a phone, it's a signal called an interrupt.
Most people never think about interrupts in operating system design. Why would they? And it's invisible. It just works. But the short version is: without interrupts, your laptop would be a glorified calculator that can only do one thing at a time and pray nothing urgent shows up That's the whole idea..
So what are we actually talking about here?
What Is an Interrupt in an Operating System
An interrupt is a signal. Practically speaking, hardware or software sends it to the CPU to say, "Hey, stop what you're doing for a second — I need attention. " The CPU pauses its current task, saves where it was, runs a small piece of code called an interrupt handler or interrupt service routine (ISR), then goes back to what it was doing.
That's it. Practically speaking, that's the core idea. But like most things in systems programming, the devil's in the details.
Hardware Interrupts vs Software Interrupts
Hardware interrupts come from outside the CPU. On the flip side, your keyboard sends one when you press a key. That's why the disk drive sends one when it's finished reading a file. The network card fires one when a packet arrives. These are asynchronous — they happen when they happen, not on a schedule.
Software interrupts are different. A program might request a service from the OS (like writing to a file) through a software interrupt. They're triggered by programs or the OS itself. Worth adding: on older systems this was the main way apps talked to the kernel. These are synchronous — the code knows it's asking for one.
Maskable and Non-Maskable
Here's a split that matters more than people realize. Most interrupts are maskable — the CPU can temporarily ignore them if it's doing something it can't pause. But a few are non-maskable (NMI). Now, these are reserved for serious stuff: memory corruption, watchdog timer failures, things where ignoring the signal means the system is about to fall over. Here's the thing — you can't turn those off. And you wouldn't want to.
The Interrupt Vector Table
The OS keeps a table — usually called the interrupt vector table or interrupt descriptor table — that maps each interrupt number to the right handler. When an interrupt fires, the CPU looks up the address, jumps there, runs the code, and returns. Think of it like a contacts list where each emergency has a specific person to call Practical, not theoretical..
Why It Matters
Why does this matter? Now, a single CPU core runs one instruction stream at a time. Here's the thing — it doesn't. Because most people assume a computer "does many things at once" by magic. What makes multitasking feel real is the OS rapidly switching between tasks — and interrupts are the mechanism that makes switching possible and timely.
Without interrupts, the OS would have to constantly poll every device. " That wastes cycles and adds latency. "Are you done yet? Here's the thing — how about now? Your mouse would feel laggy. Still, your downloads would stall. Even so, are you done yet? A keystroke might not register for half a second because the CPU was busy calculating something else and never thought to check the keyboard It's one of those things that adds up..
Turns out, interrupts are also a safety feature. Consider this: if a device fails or a program tries something illegal, the CPU can be interrupted and the OS can step in before things spread. No interrupts, no clean way to recover from errors.
And in practice, understanding this stuff helps if you ever debug a frozen system, write drivers, or just want to know why your machine sometimes spikes to 100% "system" CPU usage. That spike is often interrupt handling doing heavy lifting Turns out it matters..
How It Works
Let's get into the actual mechanics. I'll walk through what happens from signal to return Most people skip this — try not to..
The Signal Arrives
A device raises an interrupt line. On simple systems there's one line; on modern ones there are many, often with priorities. The CPU finishes its current instruction (it doesn't stop mid-instruction — that would be chaos), then checks for pending interrupts based on its priority and mask settings.
Context Save
Before jumping to the handler, the CPU pushes context onto the stack — program counter, status flags, sometimes registers. This is so the original task can resume exactly where it left off. Practically speaking, miss this step and you get corruption. Honestly, this is the part most guides get wrong by skipping — context saving is the whole reason "resume" works Easy to understand, harder to ignore..
Quick note before moving on.
The Handler Runs
The CPU looks up the interrupt vector, jumps to the ISR. That said, good handlers do the minimum: acknowledge the device, grab the data, maybe schedule a bigger task for later. In practice, they don't sit there and process everything. Worth adding: why? Because while the handler runs, other interrupts might be blocked. Long handlers = bad latency.
Return and Resume
The ISR finishes with a special return instruction. In practice, the CPU pops the saved context and continues the interrupted task like nothing happened. From that task's perspective, there was just a tiny invisible gap Worth keeping that in mind..
Interrupt Priorities and Nesting
Real systems allow interrupt nesting — a high-priority interrupt can preempt a low-priority handler. This keeps critical signals fast. But it also means you need careful design or you'll get priority inversion, where a medium thing blocks a high thing because a low thing holds a resource. Look, it gets complicated fast.
The Role of the APIC
On modern x86 systems, the Advanced Programmable Interrupt Controller (APIC) manages routing between CPUs and devices. It lets the OS send interrupts to specific cores, balance load, and handle inter-processor interrupts (one CPU poking another). Without it, SMP machines would be a mess No workaround needed..
Common Mistakes
Here's what most people get wrong when they first learn this.
They think interrupts are free. They're not. Every interrupt has overhead: context save, table lookup, handler run, restore. Fire too many and you spend more time handling interrupts than doing work. This is called interrupt storm and it's a real failure mode.
This is where a lot of people lose the thread.
Another miss: assuming handlers can take their time. Don't. On top of that, the rule is: get in, get what you need, get out. Beginners write ISRs that do disk I/O or print debug logs. Defer the rest to a thread or a bottom-half mechanism like tasklets or work queues in Linux.
And people confuse polling with interrupts as if one is always better. In practice, some high-throughput devices (like fast network cards) use interrupt coalescing — batching events to cut overhead. Pure interrupt-per-packet would melt the CPU Small thing, real impact. Simple as that..
I know it sounds simple — but it's easy to miss that disabling interrupts is a common synchronization trick. In real terms, kernel code briefly masks interrupts to protect shared data. Do it wrong and you hang the box.
Practical Tips
If you're writing code near this layer, or just tuning a system, here's what actually works.
Keep ISRs stupidly short. Move anything complex to a deferred context. Your latency will thank you.
Use interrupt affinity on multi-core boxes. Now, pin network interrupts to certain cores so they don't bounce around and trash your caches. Real talk, this alone can drop tail latency noticeably.
Watch /proc/interrupts on Linux. It shows counts per IRQ per CPU. If one line is exploding, you've found your bottleneck or a misbehaving device.
For driver work, learn your OS's bottom-half framework. Consider this: in Linux that's softirqs, tasklets, or workqueues. In Windows it's DPCs (deferred procedure calls). Same idea, different name Practical, not theoretical..
And don't disable interrupts globally unless you absolutely must. Practically speaking, scope it tight. A wide critical section with IRQs off is how you get audio glitches and missed deadlines.
FAQ
What happens if two interrupts arrive at once? The CPU picks based on priority. The higher-priority one runs first; the other waits. If they're equal, there's a fixed ordering. The lower one stays pending until the handler enables interrupts again That's the part that actually makes a difference..
Can a program cause an interrupt on purpose?
Yes. Software interrupts (like int on x86 or svc on ARM) let a program request OS services. Modern systems mostly use dedicated instructions like syscall, but the concept is the same — trap into the kernel.
Why is my system CPU usage high from interrupts? Usually a device is firing constantly — bad driver, broken hardware, or a network flood. Check IRQ counts. A stuck interrupt
line that keeps climbing without corresponding workload is a classic sign of a misconfigured device or a runaway peripheral. Sometimes it's as simple as a loose cable causing a level-triggered IRQ to never deassert, so the controller keeps screaming for attention.
Wrapping Up
Interrupts are the nervous system of a computer — quiet most of the time, critical in the moment, and disastrous when they misfire. Even so, get the interrupt layer right and everything above it gets steadier; get it wrong and the whole machine stutters. Whether you're debugging a flaky driver or squeezing microseconds out of a trading stack, the same principles hold. The core lessons are boring but true: keep handlers fast, defer real work, respect priorities, and measure before you optimize. Treat IRQs as a scarce resource, not a free signal — and your system will stay responsive when it matters most.