Add basic documentation stub

Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
This commit is contained in:
David Oberhollenzer 2018-04-14 19:14:08 +02:00
parent 0b3f53cd9f
commit cd946f0b9c
4 changed files with 271 additions and 68 deletions

68
README
View File

@ -1,68 +0,0 @@
This directory contains the source code for a tiny init devised for
the Pygos system.
The main goal of this project is to create a simple framework for:
- system boot up and initialization
- service supervision
With the additional aims of having something that:
- simply works
- is easy to understand
- is easy to configure and maintain
The init process is intended to run on top of Linux and makes use of some
Linux specific features (e.g. signalfd), but if sufficient interest exists,
it should still be possible to make it run on some BSDs or whatever else.
The init system tries to mimic the concept of unit files from systemd as
those were considered to be a good design choice.
Right now, the system is in a "basically works" proof of concept stage and
needs some more work to become usable.
There are plans for *maybe* *eventually* adding support for Linux name
spaces, seccomp filters and cgroups as needed in the medium future.
There are already a bunch of similar projects out there that have been
considered for use in the Pygos system. The reason for starting a new
one was mainly dissatisfaction with the existing ones. Other Projects
that have been considered include:
- systemd
Contains a lot of good ideas, but it is HUGE. It has tons of
dependencies. It implements tons of things that it simply shouldn't.
It has a horrid, "modern", python based, hipster build system.
It's simply too damn large and complex.
- SystemV init
A bad combination of unnecessary complexity where it isn't needed and a
complete lack of abstraction where it would be needed. Shell script
copy and paste madness. There are reasons people started developing
alternatives (other than "hurr-durr-parallel-boots").
- upstart
Seems nice overall, but needlessly big and complex for the intended
use case in Pygos. Would have needlessly added D-Bus to the system.
- OpenRC
Was already integrated into Pygos. Things turned out to be broken.
Upstream developers did not accept fixes (after ignoring them for weeks
and preferring typo fixes instead). Complaints from other people who
tried to contribute fixes were observed on Github. Complaints from
package maintainers about deteriorating code quality were observed
on the official IRC channel. Documentation is non-existent.
- daemontools and similar (runnit, s6, minit, ...)
The sixties are over. And even code from that era is more readable. The
source code for those projects should better be tossed out the window and
rewritten from scratch. If you are a first semester CS student and you
hand something like this in as a homework, the best you might get is a
well deserved slap on the back of your head.
- busybox init
Nice and simple. Probably the best fit if the rest of your user space is
busybox as well.

90
README.md Normal file
View File

@ -0,0 +1,90 @@
# About
This directory contains the source code for a tiny init devised for
the Pygos system.
The main goal of this project is to create a simple framework for:
- system boot up and initialization
- service supervision
With the additional aims of having something that:
- simply works
- is easy to understand
- is easy to configure and maintain
The init process is intended to run on top of Linux and makes use of some
Linux specific features (e.g. signalfd), but if sufficient interest exists,
it should still be possible to make it run on some BSDs or whatever else.
The init system tries to mimic the concept of unit files from systemd as those
were considered to be a good design choice.
Those parameterizeable service description files are stored in `/usr/share/init`
by default. Services are enabled by creating a symlink in `/etc/init.d`. This
can be done using the `service` command line tool.
See [docs/services.md](docs/services.md) for more information on service
description files.
See [docs/bootup.md](docs/bootup.md) for more information on what the init
daemon does during system boot.
Right now, the system is in a "basically works" proof of concept stage and
needs some more work to become usable.
There are plans for *maybe* *eventually* adding support for Linux name
spaces, seccomp filters and cgroups as needed in the medium future.
## Why
There are already a bunch of similar projects out there that have been
considered for use in the Pygos system. The reason for starting a new
one was mainly dissatisfaction with the existing ones. Other Projects
that have been considered include:
- systemd
Contains a lot of good ideas, but it is HUGE. It has tons of
dependencies. It implements tons of things that it simply shouldn't.
It has a horrid, "modern", python based, hipster build system.
It's simply too damn large and complex.
- SystemV init
A bad combination of unnecessary complexity where it isn't needed and a
complete lack of abstraction where it would be needed. Shell script
copy and paste madness. There are reasons people started developing
alternatives (other than "hurr-durr-parallel-boots").
- upstart
Seems nice overall, but needlessly big and complex for the intended
use case in Pygos. Would have needlessly added D-Bus to the system.
- OpenRC
Was already integrated into Pygos. Things turned out to be broken.
Upstream developers did not accept fixes (after ignoring them for weeks
and preferring typo fixes instead). Complaints from other people who
tried to contribute fixes were observed on GitHub. Complaints from
package maintainers about deteriorating code quality were observed
on the official IRC channel. Documentation is non-existent.
- daemon tools and similar (runnit, s6, minit, ...)
The sixties are over. And even code from that era is more readable. The
source code for those projects should better be tossed out the window and
rewritten from scratch. If you are a first semester CS student and you
hand something like this in as a homework, the best you might get is a
well deserved slap on the back of your head.
- busybox init
Nice and simple. Probably the best fit if the rest of your user space is
busybox as well.

71
docs/bootup.md Normal file
View File

@ -0,0 +1,71 @@
# System Bootup Process
## Initial Ram Disk to Rootfs transition
After mounting the root filesystem, either the kernel or the initial ram disk
startup process is expected to exec the init program from the root filesystem.
At the current time, there is no support for re-scanning the service files
*yet*, so when init is started, the final configuration in `/etc/init.d` has to
be present. As a result, we currently cannot perform mounting of `/etc/` or
packing init into the initial ram disk and doing the rootfs transition.
Also, as a result of this, changing the service configuration requires a system
reboot to be effective.
This _will_ change in the future.
## Processing Service Descriptions
The init process reads service description files from `/etc/init.d` which are
usually symlinks to actual files in `/usr/share/init`.
The exact locations may be changed through configure flags when compiling init.
Service files specify a *target* which is basically like a SystemV runlevel and
can be one of the following:
* boot
* reboot
* shutdown
* ctrlaltdel
After parsing the configuration files, the init process starts running the
services for the `boot` target in a topological order as determined by their
*before* and *after* dependencies.
Services can be of one of the following *types*:
* wait
* once
* respawn
Services of type `wait` are started exactly once and the init process waits
until they terminate before continuing with other services.
The type `once` also only runs services once, but immediately continues
starting other services in the mean time without waiting.
Services of type `respawn` also don't stall the init process and are re-started
whenever they terminate.
## Service Process Setup
If a service description contains only a single `exec` line, the init process
forks and then execs the command directly in the child process.
If the service description contains a `tty` field, the specified device file
is opened in the child process and standard I/O is redirected to it before
calling exec. Also, a new session is created.
If a service description contains multiple `exec` lines, the init process forks
off to a single child process that does the same setup as above, and then runs
the command lines sequentially by forking a second time for each one, followed
by an exec in the grand child and a wait in the original child.
If a single command line returns something other than `EXIT_SUCCESS`,
processing of multiple command lines is immediately stopped and the offending
exit status is returned to init.

110
docs/services.md Normal file
View File

@ -0,0 +1,110 @@
# Service Files
Services that can be started and managed by init are described by service
description files stored in `/usr/share/init`.
The init process actually reads from `/etc/init.d` which contains symlinks to
the actual service files.
Enabling a service means adding a symlink, disabling means removing a symlink.
Service descriptions can be parameterized. The arguments are extracted from the
name of the symlink. Currently only 1 parameter is supported. The argument
value is separated from the service name by an '@' character in the symlink
name.
Below is an annotated example for a simple, service description for a
generic, parameterized agetty service:
#
# The text that init should print out when the status of the
# service changes.
#
# The '%0' is replaced with the first argument extracted from the
# symlink name.
#
description "agetty on %0"
#
# How to run the service. 'respawn' means restart the service when it
# terminates, 'once' means run it only once and continue with other
# services in the mean while, 'wait' means run it once, but block until
# it exits.
#
type respawn
#
# When to start the service. 'boot' means when booting the system. Other
# options are 'reboot', 'shutdown' and 'ctrlaltdel'. The system always
# starts into the 'boot' target and then later transitions to one of the
# others.
#
target boot
#
# A list of service names that must be started before this service can
# be run, i.e. this services needs to be started after those.
#
# This can only refer to generic names, not specific instances. For
# instance, you can say "after getty" to make sure a service comes up after
# all gettys are started, but you cannot specify "after agetty@tty1".
#
# Similar to 'after', there is also a 'before' keyword for specifying
# dependencies.
#
after sysinit
#
# The 'tty' directive specifies a file to which all I/O of the process is
# redirected. The specified device file is used as a controlling tty for
# the process and a new session is created with the service process as
# session leader.
#
# In this example, we derive the controlling tty from the service
# description argument.
#
tty "/dev/%0"
#
# The 'exec' directive specifies the command to execute in order to start
# the service. See in the example below on how to run multiple commands.
#
# Again we use the argument to specify what terminal our getty
# should run on.
#
exec agetty %0 linux
As can be seen in this simple example, each line in a service description is
made up of a keyword, followed by one or more arguments and terminated by a
line break.
Blank lines are ignored and shell-style comments can be used.
Arguments are separated by space. Quotation marks can be used to treat
something containing spaces or comment character as a single argument.
In between quotation marks, C-style escape sequences can be used.
Argument substitution (arguments derived from the symlink name) can be
done using a '%' sign, followed by the argument index. A '%' sign can be
escaped by writing '%%'.
If a service should sequentially run multiple commands, they can be grouped
inside braces as can be seen in the following, abbreviated example:
description "mount /var"
type wait
target boot
before vfs
exec {
mount -t tmpfs none /var
mkdir /var/log -m 0755
mkdir /var/spool -m 0755
mkdir /var/lib -m 0755
mkdir /var/tmp -m 0755
mount --bind /cfg/preserve/var_lib /var/lib
}