Understanding PID 1: The Journey from init to systemd
When you power up a Linux system, a fascinating sequence of events unfolds behind the scenes. After the kernel loads into memory, it starts the very first process, known as PID 1. This process is the initialization system that brings the user space to life, orchestrating all other processes that make your system functional. But what exactly is PID 1, and how has it evolved over time?
Understanding Processes, Services, daemons
Before diving into PID 1, it's essential to understand what a process is in the context of an operating system. A process is an instance of a program in execution. It utilizes system resources like CPU time and memory to perform tasks. Every running application or service on your system is a process, each assigned a unique Process ID (PID) by the kernel.
A Service is a process running in the background, but not all background processes are considered services. A service is a background process designed for system-level functionality, managed by a service manager, and capable of operating independently and persistently. If a process is unmanaged, transient, or tied to a user session, it remains just a generic background process. For instance, if you install nginx webserver, it will be installed as a service and hence you will be able to manage it using “systemctl” commands of the systemd service manager
A daemon is a specific type of background process. It typically runs continuously, performing system-related tasks or waiting to respond to specific requests. Most services are implemented as daemons, but daemons have unique characteristics.
We will discuss process, services and daemons in detail in upcoming posts.
The Birth of init
: The Original PID 1
In the early days of Unix and Linux, the init
system was the default initialization process. As the first process started by the kernel (hence PID 1), init
had the crucial role of bootstrapping the user space and managing system processes.
How init
Worked
init
operated based on predefined configurations found in the /etc/inittab
file. This file determined the system's runlevel, which defined the state of the machine and which services should be running.
Runlevels: Numeric codes representing different modes of operation. Common runlevels included:
0: Halt the system.
1: Single-user mode for administrative tasks.
2-5: Multi-user modes with various configurations.
6: Reboot the system.
For example, runlevel 3 typically started the system in a multi-user, command-line mode, while runlevel 5 started the system with a graphical interface.
init
would execute scripts located in directories like /etc/rc.d/
or /etc/init.d/
corresponding to the selected runlevel, starting and stopping services in a sequential manner.
Drawbacks of init
While revolutionary at its inception, init
had several limitations:
Sequential Execution: Services started one after another, leading to longer boot times.
No Dependency Handling:
init
didn't account for service dependencies, potentially causing issues if a service started before another service it relied on.Static Configuration: Adapting to dynamic hardware changes or new services required manual intervention.
Limited Error Handling: If a service failed to start,
init
lacked robust mechanisms to handle or recover from the failure.
The Transition to Upstart
To address these challenges, the Upstart
initialization system was introduced by the Ubuntu project. Upstart was designed to be event-driven, allowing the system to respond dynamically to events such as hardware changes or service status updates.
Features of Upstart
Parallel Service Startup: Enabled services to start simultaneously where possible, reducing boot times.
Event-Driven Architecture: Services could start or stop in response to specific events, improving flexibility.
Backward Compatibility: Maintained support for traditional
init
scripts, easing the transition.
Despite its innovations, Upstart faced adoption challenges outside of Ubuntu and introduced complexities in managing event handling.
Enter systemd
: The Modern Initialization System
Recognizing the need for a more robust and unified solution, developers introduced systemd
, which has since become the standard initialization system for most Linux distributions.
What Makes systemd
Different?
Parallelization Capabilities: Aggressively starts services in parallel, significantly reducing boot times.
Dependency Management: Understands and manages service dependencies, ensuring they start and stop in the correct order.
Socket and D-Bus Activation: Services can be started on-demand when their functionality is needed, optimizing resource usage.
Unified Configuration with Units: Uses simple, standardized unit files for configuration, typically located in
/etc/systemd/system/
.Targets Instead of Runlevels: Replaces traditional runlevels with targets, which are more flexible and descriptive.
Understanding Targets
Targets in systemd
serve a similar purpose to runlevels but offer greater flexibility. Some common targets include:
multi-user.target
: Similar to runlevel 3, a multi-user, non-graphical mode.graphical.target
: Similar to runlevel 5, starts the system with a graphical user interface.rescue.target
: A single-user mode for system maintenance, akin to runlevel 1.
Advantages of systemd
Efficiency: Faster boot times due to concurrent service startup.
Reliability: Improved handling of dependencies and robust service management.
Extensibility: Modular design allows for additional functionalities like logging (
journald
) and device management (udevd
).
In the next post we will discuss the usage of systemd.