pid_namespaces(7)

๐Ÿ’– NAME ๐Ÿ’–

This is pid_namespaces(7) from the Miscellaneous Information Manual, bestie. ๐Ÿ’–

pid_namespaces โ€” the overview of Linux PID namespaces, periodt. ๐Ÿ’…


โœจ DESCRIPTION โœจ

Okay so first, if you want the big-picture namespace lore, go see namespaces(7). ๐Ÿ‘‘

PID namespaces isolate the process ID number space, which means processes in different PID namespaces can literally have the same PID. No cap. This lets containers do iconic stuff like suspending/resuming the set of processes in the container and migrating the container to a new host while the processes inside the container keep the same PIDs. Obsessed. ๐Ÿซถ

PIDs in a new PID namespace start at 1, kinda like a standalone system, and calls to fork(2), vfork(2), or clone(2) will produce processes with PIDs that are unique within the namespace. Slay. โœจ

To use PID namespaces, your kernel needs to be configured with the CONFIG_PID_NS option. Periodt. ๐Ÿ’…


๐ŸŽ€ The namespace init process ๐ŸŽ€

The first process created in a new namespace (i.e., the process created using clone(2) with the CLONE_NEWPID flag, or the first child created by a process after a call to unshare(2) using the CLONE_NEWPID flag) has the PID 1, and is the "init" process for the namespace (see init(1)). ๐Ÿ‘‘ This process becomes the parent of any child processes that are orphaned because a process that resides in this PID namespace terminated (see below for further details). ๐Ÿซถ

If the "init" process of a PID namespace terminates, the kernel terminates all of the processes in the namespace via a SIGKILL signal. ๐Ÿ’€ This behavior reflects the fact that the "init" process is essential for the correct operation of a PID namespace. In this case, a subsequent fork(2) into this PID namespace fail with the error ENOMEM; it is not possible to create a new process in a PID namespace whose "init" process has terminated. Such scenarios can occur when, for example, a process uses an open file descriptor for a /proc/pid/ns/pid file corresponding to a process that was in a namespace to setns(2) into that namespace after the "init" process has terminated. Another possible scenario can occur after a call to unshare(2): if the first child subsequently created by a fork(2) terminates, then subsequent calls to fork(2) fail with ENOMEM. ๐Ÿ˜ญ

Only signals for which the "init" process has established a signal handler can be sent to the "init" process by other members of the PID namespace. This restriction applies even to privileged processes, and prevents other members of the PID namespace from accidentally killing the "init" process. ๐Ÿ™ˆ

Likewise, a process in an ancestor namespace canโ€”subject to the usual permission checks described in kill(2)โ€”send signals to the "init" process of a child PID namespace only if the "init" process has established a handler for that signal. (Within the handler, the siginfo_t si_pid field described in sigaction(2) will be zero.) ๐Ÿงš SIGKILL or SIGSTOP are treated exceptionally: these signals are forcibly delivered when sent from an ancestor PID namespace. Neither of these signals can be caught by the "init" process, and so will result in the usual actions associated with those signals (respectively, terminating and stopping the process). โš ๏ธ

Starting with Linux 3.4, the reboot(2) system call causes a signal to be sent to the namespace "init" process. See reboot(2) for more details. ๐Ÿ”ฅ


๐ŸŒณ Nesting PID namespaces ๐ŸŒณ

PID namespaces can be nested: each PID namespace has a parent, except for the initial ("root") PID namespace. The parent of a PID namespace is the PID namespace of the process that created the namespace using clone(2) or unshare(2). PID namespaces thus form a tree, with all namespaces ultimately tracing their ancestry to the root namespace. Since Linux 3.7, the kernel limits the maximum nesting depth for PID namespaces to 32. ๐ŸŒฒ

A process is visible to other processes in its PID namespace, and to the processes in each direct ancestor PID namespace going back to the root PID namespace. In this context, "visible" means that one process can be the target of operations by another process using system calls that specify a process ID. Conversely, the processes in a child PID namespace can't see processes in the parent and further removed ancestor namespaces. More succinctly: a process can see (e.g., send signals with kill(2), set nice values with setpriority(2), etc.) only processes contained in its own PID namespace and in descendants of that namespace. ๐Ÿ‘€

A process has one process ID in each of the layers of the PID namespace hierarchy where it is visible, and walking back through each direct ancestor namespace through to the root PID namespace. System calls that operate on process IDs always operate using the process ID that is visible in the PID namespace of the caller. A call to getpid(2) always returns the PID associated with the namespace in which the process was created. ๐Ÿ’…

Some processes in a PID namespace may have parents that are outside of the namespace. For example, the parent of the initial process in the namespace (i.e., the init(1) process with PID 1) is necessarily in another namespace. Likewise, the direct children of a process that uses setns(2) to cause its children to join a PID namespace are in a different PID namespace from the caller of setns(2). Calls to getppid(2) for such processes return 0. ๐Ÿ˜ญ

While processes may freely descend into child PID namespaces (e.g., using setns(2) with a PID namespace file descriptor), they may not move in the other direction. That is to say, processes may not enter any ancestor namespaces (parent, grandparent, etc.). Changing PID namespaces is a one-way operation. ๐Ÿšชโžก๏ธ no take-backs.

The NS_GET_PARENT ioctl(2) operation can be used to discover the parental relationship between PID namespaces; see ioctl_nsfs(2). ๐Ÿงฌ


๐Ÿ” setns(2) and unshare(2) semantics ๐Ÿ”

Calls to setns(2) that specify a PID namespace file descriptor and calls to unshare(2) with the CLONE_NEWPID flag cause children subsequently created by the caller to be placed in a different PID namespace from the caller. (Since Linux 4.12, that PID namespace is shown via the /proc/pid/ns/pid_for_children file, as described in namespaces(7).) These calls do not, however, change the PID namespace of the calling process, because doing so would change the caller's idea of its own PID (as reported by getpid()), which would break many applications and libraries. ๐Ÿซ 

To put things another way: a process's PID namespace membership is determined when the process is created and cannot be changed thereafter. ๐Ÿ”’

Because of this, and because system calls to create a process in another namespace need to return a meaningful new PID in the namespace of their caller, the parental relationship between processes loosely mirrors the parental relationship between PID namespaces: the parent of a process is either in the same namespace or resides in an ancestor PID namespace (immediate parent or not). This is enforced by the design of clone(2) and unshare(2), while setns(2) is restricted to only accept the current PID namespace and its descendants. ๐Ÿ’ฏ

A process may call unshare(2) with the CLONE_NEWPID flag only once. After it has performed this operation, its /proc/pid/ns/pid_for_children symbolic link will be empty until the first child is created in the namespace. 1๏ธโƒฃ


๐Ÿผ Adoption of orphaned children ๐Ÿผ

When a child process becomes orphaned, it is reparented to the "init" process in the PID namespace of its parent (unless one of the nearer ancestors of the parent employed the prctl(2) PR_SET_CHILD_SUBREAPER command to mark itself as the reaper of orphaned descendant processes). Note that because of the setns(2) and unshare(2) semantics described above, this may be the "init" process in the PID namespace that is the parent of the child's PID namespace, rather than the "init" process in the child's own PID namespace. ๐Ÿซ‚


๐Ÿงฉ Compatibility of CLONE_NEWPID with other CLONE_* flags ๐Ÿงฉ

In current versions of Linux, CLONE_NEWPID can't be combined with CLONE_THREAD. Threads are required to be in the same PID namespace such that the threads in a process can send signals to each other. Similarly, it must be possible to see all of the threads of a process in the proc(5) filesystem. Additionally, if two threads were in different PID namespaces, the process ID of the process sending a signal could not be meaningfully encoded when a signal is sent (see the description of the siginfo_t type in sigaction(2)). Since this is computed when a signal is enqueued, a signal queue shared by processes in multiple PID namespaces would defeat that. ๐Ÿ’€

In earlier versions of Linux, CLONE_NEWPID was additionally disallowed (failing with the error EINVAL) in combination with CLONE_SIGHAND (before Linux 4.3) as well as CLONE_VM (before Linux 3.12). The changes that lifted these restrictions have also been ported to earlier stable kernels. โณ


๐Ÿ“‚ /proc and PID namespaces ๐Ÿ“‚

A /proc filesystem shows (in the /proc/pid directories) only processes visible in the PID namespace of the process that performed the mount, even if the /proc filesystem is viewed from processes in other namespaces. ๐Ÿ‘๏ธ

After creating a new PID namespace, it is useful for the child to change its root directory and mount a new procfs instance at /proc so that tools such as ps(1) work correctly. If a new mount namespace is simultaneously created by including CLONE_NEWNS in the flags argument of clone(2) or unshare(2), then it isn't necessary to change the root directory: a new procfs instance can be mounted directly over /proc. โœจ

From a shell, the command to mount /proc is:

$ mount -t proc proc /proc

Calling readlink(2) on the path /proc/self yields the process ID of the caller in the PID namespace of the procfs mount (i.e., the PID namespace of the process that mounted the procfs). This can be useful for introspection purposes, when a process wants to discover its PID in other namespaces. ๐Ÿ”


๐Ÿ“„ /proc files ๐Ÿ“„

  • /proc/sys/kernel/ns_last_pid (since Linux 3.3) โ€” This file (which is virtualized per PID namespace) displays the last PID that was allocated in this PID namespace. When the next PID is allocated, the kernel will search for the lowest unallocated PID that is greater than this value, and when this file is subsequently read it will show that PID. ๐Ÿ‘‘

This file is writable by a process that has the CAP_SYS_ADMIN or (since Linux 5.9) CAP_CHECKPOINT_RESTORE capability inside the user namespace that owns the PID namespace. This makes it possible to determine the PID that is allocated to the next process that is created inside this PID namespace. ๐ŸŽฏ


๐Ÿงƒ Miscellaneous ๐Ÿงƒ

When a process ID is passed over a UNIX domain socket to a process in a different PID namespace (see the description of SCM_CREDENTIALS in unix(7)), it is translated into the corresponding PID value in the receiving process's PID namespace. โœ‰๏ธ


๐ŸŒˆ STANDARDS ๐ŸŒˆ

Linux. ๐Ÿง

โœจ EXAMPLES โœจ

Ok so bestie, the examples situation here is giving "go touch grass and read the sibling page" ๐Ÿ’… โ€” the actual worked examples live elsewhere.


๐ŸŒธ SEE ALSO ๐ŸŒธ

The girlies you should def befriend next ๐Ÿ‘‘ โ€” go read these, fr fr:

That's the whole squad right there โœจ read them and you'll be unbothered, unfiltered, and fully namespace-pilled ๐Ÿ’–


And that's a wrap on the whole page, bestie!! ๐ŸŽ€ This one came straight out of Linux man-pages 6.20, dated 2026-05-13 โ€” so if you're quoting it in a group chat, that's the vibe check receipt. ๐Ÿ’œ Go forth and fork responsibly, ily, mwah ๐Ÿ˜ญ๐Ÿซถ๐Ÿ’…

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms