Documentation Boot Beat
systemd is a system and service manager, replacement for SysVinit and Upstart.
After a six months shift, during witch it has been more granulary tested, F15 brings in, by default, a new system daemon whose code is designed from scratch, entirely by a Fedora developer and RH employer, inspired on the design/functionality of launchd daemon, on Mac OS.
systemd starts up and supervises the entire system and is based around the notion of units composed of a name and a type and matching a configuration file with the same name and type (e.g. a unit avahi.service has a configuration file with the same name and is a unit encapsulating the Avahi daemon). There are seven types of unit:
- service: these are the most obvious kind of unit: daemons that can be started, stopped, restarted, reloaded. For compatibility with SysV systend not only support his own configuration files for services, but also is able to read classic SysV init scripts, in particular it parses the LSB header, if it exists. /etc/init.d is hence not much more than just another source of configuration.
- socket: this unit encapsulates a socket in the file-system or on the Internet. systemd currently support AF_INET, AF_INET6, AF_UNIX sockets of the types stream, datagram, and sequential packet. It can also support classic FIFOs as transport. Each socket unit has a matching service unit, that is started if the first connection comes in on the socket or FIFO (e.g. nscd.socket starts nscd.service on an incoming connection).
- device: this unit encapsulates a device in the Linux device tree. If a device is marked for this via udev rules, it will be exposed as a device unit in systemd. Properties set with udev can be used as configuration source to set dependencies for device units.
- mount: this unit encapsulates a mount point in the file system hierarchy. systemd monitors all mount points how they come and go, and can also be used to mount or unmount mount-points. /etc/fstab is used here as an additional configuration source for these mount points, similar to how SysV init scripts can be used as additional configuration source for service units.
- automount: this unit type encapsulates an automount point in the file system hierarchy. Each automount unit has a matching mount unit, which is started (i.e. mounted) as soon as the automount directory is accessed.
- target: this unit type is used for logical grouping of units: instead of actually doing anything by itself it simply references other units, which thereby can be controlled together. (e.g. multi-user.target, which is a target that basically plays the role of run-level 5 on classic SysV system; or bluetooth.target which is requested as soon as a bluetooth dongle becomes available and which simply pulls in bluetooth related services that otherwise would not need to be started: bluetoothd and obexd and suchlike).
- snapshot: similar to target units snapshots do not actually do anything themselves and their only purpose is to reference other units. Snapshots can be used to save/rollback the state of all services and units of the init system. Primarily it has two intended use cases: to allow the user to temporarily enter a specific state such as "Emergency Shell", terminating current services, and provide an easy way to return to the state before, pulling up all services again that got temporarily pulled down. And to ease support for system suspending: still many services cannot correctly deal with system suspend, and it is often a better idea to shut them down before suspend, and restore them afterwards.
- aggressive parallelization capabilities using socket: to speed up the entire boot and start more processes in parallel, systemd creates the listening sockets before actually starting the daemon, and then just passes the socket to it. All sockets for all daemons are created in one step in the init system, and then in a second step run all daemons at once. If a service needs another, and it is not fully started up, what will happen is that the connection is queued in the providing service and the client will potentially block on that single request. But only that one client will block and only on that one request. Also, dependencies between services no longer have to be configured to allow proper parallelized start-up: starting all sockets at once and a service needing another, it surely can connect to its socket.
- D-Bus activation for starting services: using bus activation, a service can be started the first time it is accessed. Bus activation also gives the minimal per-request synchronisation needed for starting up the providers and the consumers of D-Bus services at the same time: starting a service at the same time as another, if one is quicker, than via the bus activation logic we can get D-Bus to queue the request until the otehr manages to establish its service name.
- offers on-demand starting of daemons:
- keeps track of processes using Linux cgroups: kernel Control Groups or hierarchy of groups of processes. If a process in a specific cgroup forks, its child will become a member of the same group. Unless it is privileged and has access to the cgroup file system it cannot escape its group. cgroups let enforce limits on entire groups of processes. cgroups are also useful to enforce limits outside of the immediate container use case (e.g. limit the total amount of memory or CPU, Apache and all its children may use, so a misbehaving CGI script can no longer escape your resource control by simply forking away.) In addition to container and resource limit enforcement cgroups are very useful to keep track of daemons: cgroup membership is securely inherited by child processes, they cannot escape. There's a notification system available so that a supervisor process can be notified when a cgroup runs empty. You can find the cgroups of a process by reading /proc/$PID/cgroup. cgroups hence make a very good choice to keep track of processes for tracking purposes.
- supports snapshotting and restoring of the system state: snapshots can be used to save/rollback the state of all services and units of the init system. Primarily it has two intended use cases: to allow the user to temporarily enter a specific state such as "Emergency Shell", terminating current services, and provide an easy way to return to the state before, pulling up all services again that got temporarily pulled down.
- maintains mount and automount points: systemd monitors all mount points how they come and go, and can also be used to mount or unmount mount-points. /etc/fstab can be used here as an additional configuration source for these mount points. Using the
comment=fstab option you can even mark
/etc/fstabentries to become systemd controlled automount points..
- implements an elaborate transactional dependency-based service control logic: systemd supports several kinds of dependencies between services (or units). After/Before can be used to fix the ordering how units are activated. It is completely orthogonal to Requires and Wants, which express a positive requirement dependency, either mandatory, or optional. Then, there is Conflicts which expresses a negative requirement dependency. If a service (or unit) is requested to start up or shut down, systemd will add it and all its dependencies to a temporary transaction. Then, it will verify if the transaction is consistent (i.e. whether the ordering via After/Before of all units is cycle-free). If it is not, systemd will try to fix it up, and removes non-essential jobs from the transaction that might remove the loop. Also, systemd tries to suppress non-essential jobs in the transaction that would stop a running service. Non-essential jobs are those which the original request did not directly include but which where pulled in by Wants type of dependencies. Finally systemd checks whether the jobs of the transaction contradict jobs that have already been queued, and optionally the transaction is aborted then. If all worked out and the transaction is consistent and minimized in its impact it is merged with all already outstanding jobs and added to the run queue. Effectively this means that before executing a requested operation, we will verify that it makes sense, fixing it if possible, and only failing if it really cannot work.
It can work as a drop-in replacement for sysvinit.
It is implemented around the notion of units. Units have a name and a type, whose configuration is in a file with the same name. There are several kinds of units: service, socket, device, others.