The man page specifies that you may be interested in using --fork
and --mount-proc
when creating a PID namespace, but why those options are not default?
1 Answer
Linux namespaces are created using the unshare(2)
system call. The unshare
program is simply a thin wrapper around the unshare(2)
system call that exposes namespace functionality in a way that remains close to as flexible as the underlying system call.
For most namespaces, unshare(2)
modifies the calling processes runtime environment, detaching it from the parent namespace, and associating it with a new, typically empty namespace. For example a process that unshares itself from the network namespace immediately sees a new, empty network namespace with no devices.
The PID namespace, however works differently. When unshare()
is called to detach a PID namespace, it doesn't modify the calling processes runtime environment, but instead causes the child process after a fork()
to enter the new pid namespace, and receive PID 1 within the new namespace. The PID 1 is reserved for the init
process.
As to likely reasons why the --fork
and --mount-proc
are not the default options:
--fork
is likely not the default as no other namespace requires a fork, and having the--fork
as a separate options keeps the behavior of the--pid
option consistent with how the other namespace options map directly tounshare(2)
flags.--mount-proc
is likely not the default as it implies a mount namespace (--mount
), and this similarly to--fork
performs additional actions besidesunshare(2)
with the appropriate flags.
To properly make use of PID namespaces requires a special program that is purposefully designed to take the role of init
within the new namespace. Inside the new PID namespace, the process with pid
1 has three unique features when compared to other processes:
1) It does automatically receive default signal handers. This means that signals sent to it are ignored unless it the process explicitly registers signal handlers the signals.
2) If another process in the namespace dies before its children, its children will be reparented to the process with pid 1. This allows init
to collect the exit status from the process so that the kernel can remove it from the process table.
3) If the process with PID 1 dies, every other process in the pid namespace will be forcibly terminated and the namespace destroyed.
For these reasons application processes usually aren't suitable to run as PID 1 within a PID namespace.
The addition of namespaces for various kernel controlled resources was primarily motivated by container technology, in particular system containers that which offer an environment very similar to conventional virtual machines (VMS) but without the overhead that comes with running a separate kernel simulating hardware to the VMs. Early on as namespaces were introduced to the Linux kernel (mainly between Linux 2.4.19 - 3.8), PID namespaces were introduced after Mount, UTS, IPC, and Network namespaces. Early versions of unshare
set a precedent as how the different namespace options were expected to behave.
Before full-fledged container frameworks such as LXC and Docker were available, unshare
could be used as a makeshift utility to spawn an init
daemon (such as systemd
) inside a new container (consisting of a new PID namespace and possibly other unshared namespaces). Such frameworks include their own functionality for launching containers without the need for unshare
. Modern versions of systemd
also support this functionality without the need for a separate unshare
utility.