我正在研究一些内核代码并试图了解数据结构是如何链接在一起的。我知道调度程序如何工作的基本概念,以及 PID 是什么。但是我不知道在这种情况下命名空间是什么,也无法弄清楚所有这些是如何协同工作的。
我已经阅读了一些解释(包括 O'Reilly “Understanding the Linux Kernel”的部分内容)并理解可能是同一个 PID 进入了两个进程,因为一个进程已经终止并且 ID 被重新分配。但我无法弄清楚这一切是如何完成的。
所以:
task_struct
之间有什么关系?和 pid_namespace
? (我已经认为它与 pid_t
有关,但不知道如何)一些引用资料:
pid_namespace
的定义task_struct
的定义upid
的定义(另见 pid
正下方)最佳答案
也许这些链接可能会有所帮助:
通过第二个链接后,很明显命名空间是隔离资源的好方法。在包括 Linux 在内的任何操作系统中,进程都是最重要的资源之一。用他自己的话说
Yes, that’s it, with this namespace it is possible to restart PID numbering and get your own “1″ process. This could be seen as a “chroot” in the process identifier tree. It’s extremely handy when you need to deal with pids in day to day work and are stuck with 4 digits numbers…
因此,您可以创建自己的私有(private)流程树,然后将其分配给特定用户和/或特定任务。在这棵树中,进程不必担心 PID 与“容器”外的 PID 冲突。因此,这与将这棵树完全交给不同的“根”用户一样好。这位好人已经做了一个很棒的工作,用一个很好的小例子来解释这些事情,所以我不会在这里重复。
就内核而言,我可以为您提供一些指导以帮助您入门。我不是这里的专家,但我希望这对您有所帮助。
此 LWN article ,描述了查看 PID 的旧方法和新方法。用它自己的话来说:
All the PIDs that a task may have are described in the
struct pid
. This structure contains the ID value, the list of tasks having this ID, the reference counter and the hashed list node to be stored in the hash table for a faster search. A few more words about the lists of tasks. Basically a task has three PIDs: the process ID (PID), the process group ID (PGID), and the session ID (SID). The PGID and the SID may be shared between the tasks, for example, when two or more tasks belong to the same group, so each group ID addresses more than one task. With the PID namespaces this structure becomes elastic. Now, each PID may have several values, with each one being valid in one namespace. That is, a task may have PID of 1024 in one namespace, and 256 in another. So, the formerstruct pid
changes. Here is how thestruct pid
looked like before introducing the PID namespaces:struct pid { atomic_t count; /* reference counter */ int nr; /* the pid value */ struct hlist_node pid_chain; /* hash chain */ struct hlist_head tasks[PIDTYPE_MAX]; /* lists of tasks */ struct rcu_head rcu; /* RCU helper */ };
And this is how it looks now:
struct upid { int nr; /* moved from struct pid */ struct pid_namespace *ns; /* the namespace this value * is visible in */ struct hlist_node pid_chain; /* moved from struct pid */ }; struct pid { atomic_t count; struct hlist_head tasks[PIDTYPE_MAX]; struct rcu_head rcu; int level; /* the number of upids */ struct upid numbers[0]; };
As you can see, the
struct upid
now represents the PID value -- it is stored in the hash and has the PID value. To convert thestruct pid
to the PID or vice versa one may use a set of helpers liketask_pid_nr()
,pid_nr_ns()
,find_task_by_vpid()
, etc.
虽然有点过时,但这些信息足以让您入门。这里还有一个更重要的结构需要提及。是
struct nsproxy
.这个结构是所有事物命名空间相对于它所关联的进程的焦点。它包含一个指向 的指针。此进程的子进程将使用的 PID 命名空间 .当前进程的 PID 命名空间使用 task_active_pid_ns
找到。 .在
struct task_struct
内,我们有一个命名空间代理指针,恰本地称为 nsproxy
,它指向这个进程的 struct nsproxy
结构体。如果您跟踪创建新流程所需的步骤,您可以找到 task_struct
之间的关系。 , struct nsproxy
和 struct pid
.Linux 中的新进程总是从现有进程中派生出来,然后使用
execve
替换它的镜像(或 exec 系列的类似功能)。因此,作为 do_fork
的一部分, copy_process
被调用。作为复制父进程的一部分,会发生以下重要事情:
task_struct
首先使用 dup_task_struct
复制. copy_namespaces
复制父进程的命名空间.这也创建了一个新的 nsproxy
子结构,它的 nsproxy 指针指向这个新创建的结构 PID
使用 alloc_pid
分配结构它实际上为新的 fork
分配了一个新的 PID 结构。编辑过程。此函数的简短片段:nr = alloc_pidmap(tmp);
if(nr<0)
goto out_free;
pid->numbers[i].nr = nr;
pid->numbers[i].ns = tmp;
这填充
upid
通过给它一个新的 PID 以及它当前所属的命名空间来构建结构。进一步作为
copy process
的一部分函数,这个新分配的 PID 然后链接到相应的 task_struct
通过函数pid_nr
即它的全局 ID(从 INIT 命名空间中看起来是原始 PID nr)存储在字段 pid
中在 task_struct
.在
copy_process
的最后阶段, task_struct
之间建立链接还有这个新的pid
结构通过pid_link
task_struct
内的字段通过函数attach_pid
.它还有很多,但我希望这至少能给你一些先机。
注意:我指的是最新的(截至目前)内核版本,即。 3.17.2.
关于linux-kernel - `task_struct` 和 `pid_namespace` 之间有什么关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26779416/