Fundamentals 29 min read

Linux Kernel Source Walkthrough: The Five Core Subsystems

This article explains the Linux kernel architecture, breaks it into three layers and five key subsystems—process scheduling, memory management, virtual file system, network interface, and inter‑process communication—detailing their responsibilities, inter‑dependencies, and providing concrete code examples and diagrams.

Linux Kernel Journey
Linux Kernel Journey
Linux Kernel Journey
Linux Kernel Source Walkthrough: The Five Core Subsystems

Linux Kernel Architecture Overview

A familiar diagram shows the GNU/Linux system stack: user (application) space sits above kernel space, where the Linux kernel resides. The kernel is divided into three layers: the system‑call interface, architecture‑independent kernel code, and architecture‑specific BSP code.

Five Core Kernel Subsystems

The kernel’s main functionality is provided by five subsystems:

Process Scheduling (SCHED)

Memory Management (MM)

Virtual File System (VFS)

Network Interface (NET)

Inter‑Process Communication (IPC)

All subsystems share common resources such as memory allocation routines, logging functions, and debugging utilities.

Process Scheduling

Process scheduling controls CPU access for multiple processes, enabling "micro‑serial, macro‑parallel" execution. It is central because every other subsystem may need to suspend or resume a process.

Linux defines several process states:

TASK_RUNNING : running or ready to run.

TASK_INTERRUPTIBLE : sleeping but can be awakened by a signal.

TASK_UNINTERRUPTIBLE : sleeping and cannot be interrupted.

TASK_ZOMBIE : terminated, waiting for parent to reap.

TASK_STOPPED : stopped by an external signal (e.g., SIGSTOP).

Device drivers may put a process to sleep when a requested resource is unavailable, waking it once the resource is released.

Process creation uses fork() to duplicate the parent’s address space, followed by exec() to load a new program.

Memory Management

Memory management ensures safe sharing of main memory among processes, translating virtual addresses to physical ones via the MMU. Each process typically has a 4 GB address space: 0‑3 GB for user space, 3‑4 GB for kernel space.

The kernel space contains several regions:

Direct‑mapped area (3 GB – 3 GB+896 MB)

Vmalloc area

Permanent mapping area

Fixed mapping area

Linux uses a slab allocator to manage 4 KB pages and higher‑level structures, and supports swapping pages to disk when physical memory is exhausted. Source code resides in ./linux/mm.

Virtual File System (VFS)

VFS abstracts hardware‑specific details, providing a uniform interface for all file systems. It uses superblocks to store filesystem metadata, inodes for file information, and dentries for directory entries.

All file types—regular files, directories, character devices, block devices, sockets—are treated as files, enabling programs to use the same I/O calls regardless of the underlying filesystem (e.g., ext2, vfat).

Network Interface

The network subsystem consists of protocol layers and driver layers. The protocol layer offers a uniform packet‑send/receive API (e.g., dev_queue_xmit(), netif_rx()), while the driver layer implements hardware‑specific operations via the net_device structure.

Typical data flow: user process → socket → network protocol → network driver → hardware.

Inter‑Process Communication (IPC)

Linux provides several IPC mechanisms, each with distinct characteristics and APIs.

Pipes (Unnamed)

Pipes are half‑duplex byte streams created with pipe(fd[2]). After fork(), the parent can write to fd[1] and the child can read from fd[0].

#include <stdio.h>
int pipe(int fd[2]); // returns 0 on success, -1 on failure

Example workflow:

#include <stdio.h>
#include <stdlib.h>
int main(){
    int fd[2];
    pid_t pid;
    if(pipe(fd) < 0){ perror("Create Pipe Error!"); }
    if((pid = fork()) < 0){ perror("Fork Error!"); }
    else if(pid > 0){ // parent
        close(fd[0]);
        write(fd[1], "Hello World
", 12);
    } else { // child
        close(fd[1]);
        char buf[20];
        read(fd[0], buf, 20);
        printf("%s", buf);
    }
    return 0;
}

FIFO (Named Pipe)

Created with mkfifo(const char *pathname, mode_t mode). Unlike unnamed pipes, FIFOs can be accessed by unrelated processes using a pathname.

#include <stdio.h>
int mkfifo(const char* pathname, mode_t mode); // returns 0 on success, -1 on error

Opening a FIFO without O_NONBLOCK blocks until the opposite end is opened; with O_NONBLOCK, reads return immediately and writes fail with ENXIO if no reader is present.

Message Queues

Message queues store messages in kernel space, identified by a queue ID.

#include <stdio.h>
int msgget(key_t key, int flag);
int msgsnd(int msqid, const void *ptr, size_t size, int flag);
int msgrcv(int msqid, void *ptr, size_t size, long type, int flag);
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

The type argument controls retrieval order: 0 for the first message, >0 for the first message of that type, <0 for the first message with a type ≤ |type|.

Semaphores

Semaphores implement synchronization. The API includes semget(), semop(), and semctl(). The sembuf structure defines the operation:

struct sembuf {
    short sem_num; // semaphore index
    short sem_op;  // operation value
    short sem_flg; // flags (IPC_NOWAIT, SEM_UNDO)
};

Operations with sem_op > 0 release resources; sem_op < 0 request resources, potentially blocking depending on flags.

Shared Memory

Shared memory provides the fastest IPC. Creation and attachment use shmget() and shmat():

#include <stdio.h>
int shmget(key_t key, size_t size, int flag);
void *shmat(int shm_id, const void *addr, int flag);
int shmdt(void *addr);
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);

After attachment, processes can read/write the memory directly; shmdt() detaches it without deleting the segment, while shmctl(..., IPC_RMID, ...) removes it from the system.

Dependency Relationships

Key dependencies include:

Process scheduling ↔ memory management: creating a process requires allocating memory.

IPC ↔ memory management: shared‑memory IPC relies on the memory manager.

VFS ↔ network interface: VFS uses network drivers for NFS and RAMDISK devices.

Memory management ↔ VFS: swapping involves both subsystems.

All subsystems also share common kernel routines for allocation, logging, and debugging.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

memory managementkernelLinuxshared memoryIPCprocess schedulingvfssubsystemspipessemaphores
Linux Kernel Journey
Written by

Linux Kernel Journey

Linux Kernel Journey

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.