1 Linux Operating System 許 ¯Œ ç“. 2 NameSpace Namespace [Michael Kerrisk]Michael Kerrisk Currently, Linux implements six different types of namespaces

  • View
    224

  • Download
    0

Embed Size (px)

Text of 1 Linux Operating System 許 ¯Œ ç“. 2 NameSpace Namespace...

  • *Linux Operating System

  • *

    NameSpace

  • Namespace [Michael Kerrisk]Currently, Linux implements six different types of namespaces. TheCLONE_NEW*identifiers listed in parentheses are the names of the constants used to identify namespace types when employing the namespace-related APIs (clone(),unshare(), andsetns() )*

  • Six Linux NamespacesMount namespaces(CLONE_NEWNS, Linux 2.4.19)UTS namespaces(CLONE_NEWUTS, Linux 2.6.19)IPC namespaces(CLONE_NEWIPC, Linux 2.6.19)PID namespaces(CLONE_NEWPID, Linux 2.6.24)Network namespaces(CLONE_NEWNET, Linux 2.6.29)User namespaces(CLONE_NEWUSER, Linux 3.8)*

  • Goals of Namespace (1) [Michael Kerrisk]The purpose of each namespace is to wrap a particular global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource.*

  • Goals of Namespace (2) [Michael Kerrisk]One of the overall goals of namespaces is to support the implementation ofcontainers, a tool for lightweight virtualization (as well as other purposes) that provides a group of processes with the illusion that they are the only processes on the system*

  • PID Namespace [Michael Kerrisk]The global resource isolated by PID namespaces is the process ID number space. This means that processes in different PID namespaces can have the same process ID.PID namespaces are used to implement containers that can be migrated between host systems while keeping the same process IDs for the processes inside the container.*

  • Process PID [Michael Kerrisk]As with processes on a traditional Linux (or UNIX) system, the process IDswithina PID namespace are unique, and are assigned sequentially starting with PID 1.Likewise, as on a traditional Linux system, PID 1theinitprocessis special: it is the first process created within the namespace, and it performs certain management tasks within the namespace.*

  • Creation of a New PID Namespace [Michael Kerrisk]A new PID namespace is created by calling clone() with the CLONE_NEWPID flag.

    child_pid = clone(childFunc, child_stack, CLONE_NEWPID | SIGCHLD, argv[1]);*

  • PID Namespace Hierarchy[Michael Kerrisk]PID namespaces form a hierarchy: A process can "see" only those processes contained in its own PID namespace and in the child namespaces nested below that PID namespace. If the parent of the child created byclone()is in a different namespace, the child cannot "see" the parent; therefore,getppid()reports the parent PID as being zero.*

  • PID Namespace Hierarchy [text book]*

  • /proc/PIDDirectory[Michael Kerrisk]Within a PID namespace, the/proc/PIDdirectories show information only about processes within that PID namespace orprocesses within one of its descendant namespaces.*

  • Mount a proc filesystem[Michael Kerrisk]However, in order to make the/proc/PIDdirectories that correspond to a PID namespace visible, the proc filesystem ("procfs" for short) needs to be mounted from within that PID namespace. From a shell running inside the PID namespace (perhaps invoked via thesystem() library function), we can do this using amountcommand of the following form:

    # mount -t proc proc /mount_point

    *

  • Nested PID Namespaces[Michael Kerrisk]PID namespaces are hierarchically nested in parent-child relationships.Within a PID namespace, it is possible to seeall other processes in the same namespace, as well asall processes that are members of descendant namespaces. *

  • See a Process [Michael Kerrisk]Here, "see" means being able to make system calls that operate on specific PIDs.e.g., usingkill()to send a signal to process.Processes in a child PID namespace cannot see processes that exist (only) in the parent PID namespace (or further removed ancestor namespaces).*

  • PID returned by getpid() [Michael Kerrisk]A process will have one PID in each of the layers of the PID namespace hierarchy starting from the PID namespace in which it resides through to the root PID namespace.Calls togetpid()always report the PID associated with the namespace in which the process resides

    *

  • Traditional init Process and SignalsThe traditional Linuxinitprocess is treated specially with respect to signals. The only signals that can be delivered toinitare those for which the process has established a signal handler.All other signals are ignored. This prevents theinitprocesswhose presence is essential for the stable operation of the system from being accidentally killed, even by the super user.*

  • init Processes of Namespaces and SignalsPID namespaces implement some analogous behavior for the namespace-specificinitprocess.Other processes in the namespace (even privileged processes) can send only those signals for which theinit process has established a signal handler. Note that (as for the traditionalinitprocess) the kernel can still generate signals for the PID namespaceinitprocess in all of the usual circumstancese.g., hardware exceptions, terminal-generated signals such asSIGTTOU, and expiration of a timer.*

  • Signals from Ancestor NamespacesSignals can be sent to the PID namespaceinitprocess by processes in ancestor PID namespaces.Again, only the signals for which theinitprocess has established a handler can be sent, with two exceptions:SIGKILL andSIGSTOP. *

  • init Process and SIGKILL and SIGSTOP When a process in an ancestor PID namespace sends SIGKILL and SIGSTOP to theinitprocess, they are forcibly delivered (and can't be caught).The SIGSTOP signal stops the init process; SIGKILL terminates it.*

  • Termination of init ProcessesSince theinitprocess is essential to the functioning of the PID namespace, if the init process is terminated by SIGKILL(or it terminates for any other reason), the kernel terminates all other processes in the namespace by sending them aSIGKILLsignal.*

  • Connection between Processes and Namespaces*struct nsproxy *nsproxy;

  • Definition of struct nsproxystruct nsproxy { atomic_t count; struct uts_namespace *uts_ns; struct ipc_namespace *ipc_ns; struct mnt_namespace *mnt_ns; struct pid_namespace *pid_ns; struct net *net_ns;};

    A nsproxy is shared by processes which share all namespaces. As soon as a single namespace is cloned or unshared, the nsproxy is copied.

    *

  • struct nsproxyA structure to contain pointers to all per-process namespaces - fs (mount), uts, network, ipc, etc.'count' is the number of processes holding a reference.*

  • Initial Global Namespacestruct nsproxy init_nsproxy = { .count = ATOMIC_INIT(1), .uts_ns = &init_uts_ns, #if defined(CONFIG_POSIX_MQUEUE)|| defined(CONFIG_SYSVIPC) .ipc_ns = &init_ipc_ns, #endif .mnt_ns = NULL, .pid_ns = &init_pid_ns, #ifdef CONFIG_NET .net_ns = &init_net, #endif };*

  • Process Identification NumberUnix processes are always assigned a number to uniquely identify them in their namespace. This number is called the process identification number or PID for short. Each process generated with fork or clone is automatically assigned a new unique PID value by the kernel.*

  • *Process IDPIDs are numbered sequentially in each PID namespace: the PID of a newly created process is normally the PID of the previously created process increased by one.

    Of course, there is an upper limit on the PID values; when the kernel reaches such limit, it must start recycling the lower, unused PIDs. By default, the maximum PID number is PID_MAX_LIMIT-1 (32,767 or 262143).

  • Maximum PID Number#define PAGE_SHIFT 12

    #define PAGE_SIZE 1UL 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))

    P.S.: PID_MAX_LIMIT is equal to 215 (32768) or 224.

    #define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)

    P.S.: PIDMAP_ENTRIES is equal to 1 or 215.

    *

  • PIDs in PID NamespacesNamespaces add some additional complexity to how PIDs are managed.PID namespaces are organized in a hierarchy. *

  • A Process May Have Multiple PIDs When a new namespace is created, all PIDs that are used in this namespace are visible to the parent namespace, but the child namespace does not see PIDs of the parent namespace.However this implies that some processes are equipped with more than one PID, namely, one per namespace they are visible in. This must be reflected in the data structures. *

  • Global IDsGlobal IDs are identification numbers that are valid within the kernel itself and in the initial global namespace. For each ID type, a given global identifier is guaranteed to be unique in the whole system.*

  • Local IDsLocal IDs belong to a specific namespace and are not globally valid. For each ID type, they are valid within the namespace to which they belong, but identifiers of identical type may appear with the same ID number in a different namespace.*

  • Global PID and TGIDThe global PID and TGID are directly stored in the task_struct, namely, in the elements pid and tgid:

    typedef int __kernel_pid_t;typedef __kernel_pid_t pid_t;struct task_struct { ... pid_t pid; pid_t tgid; ...}*

  • *PIDs and ProcessesLinux associates a different PID with each process or lightweight process in the system. As we shall see later in this chapter, there is a tiny exception on multiprocessor systems.This approach allows the maximum flexibility, because every execution context in the system can be uniquely identified.

  • *Threads in the Same Group Must Have a Common PID On the other hand, Unix programmers expect threads in the same group to have a common PID. For instance, it should be