Linux Fundamentals for Embedded Systems
Why appliance-style devices run embedded Linux, and the kernel basics worth actually knowing.
Questions
Easy / Med / Hard
Your accuracy
A lot of what people picture as "embedded" is a small bare-metal microcontroller looping over sensor reads. A network security appliance is a different animal: it's closer to a small, purpose-built computer, and it very often runs a stripped-down Linux rather than a classic RTOS -- which is why Linux fundamentals are a real, frequently-tested part of this kind of interview rather than a side topic.
Why Linux, on a dedicated appliance, instead of writing everything bare-metal? Because a kernel that already has a TCP/IP stack, device drivers, a filesystem, and process isolation is an enormous amount of correct, tested infrastructure you don't have to write yourself -- and a networking appliance's entire job is moving and inspecting network traffic, which is exactly the part of the OS that's most mature. The tradeoff is size, boot time, and less deterministic timing than a purpose-built RTOS, which is why the harder real-time constraints in this space (packet-processing fast paths) are often pushed into dedicated hardware or kernel-bypass techniques rather than handled in ordinary user-space code.
The kernel mediates every interaction between a program and the hardware or other programs. User-space code doesn't touch hardware directly; it asks the kernel to, through a system call -- read, write, open, fork, socket are all system calls, a controlled, checked doorway between an unprivileged process and the privileged kernel. That privilege split (user mode vs. kernel mode) is a hardware-enforced boundary, not just a convention -- it's what stops a bug in one process from directly corrupting the kernel or another process's memory.
A process is the OS's unit of isolation: its own memory space, its own file descriptors, scheduled independently. fork() creates a near-exact copy of the calling process; exec() replaces a process's memory with a different program entirely. The common pattern of calling fork() followed by exec() in the child is literally how a shell launches every command you type.
A file descriptor is a small integer the kernel hands back for an open resource -- a file, a socket, a pipe -- and it's the handle every subsequent read/write/close call uses. The fact that sockets are file descriptors too, not a separate concept, is why so much of the networking API looks like ordinary file I/O: the kernel deliberately unified the interface.
Everything above assumes a process boundary. Kernel modules, by contrast, run inside the kernel itself with no such isolation -- a bug in one can crash the whole system, which is exactly the tradeoff a device driver author is making by choosing to live in kernel space rather than user space.