roo*_*ook 38 linux apache kernel linux-kernel
Linux如何确定它将用于进程的下一个PID?这个问题的目的是为了更好地理解Linux内核.不要害怕发布内核源代码.如果顺序分配PID,Linux如何填补空白?当它到达终点时会发生什么?
例如,如果我从Apache运行一个PHP脚本,那么<?php print(getmypid());?>在刷新时会打印出相同的PID几分钟.这段时间是apache接收的请求数量的函数.即使只有一个客户端,PID最终也会改变.
当PID改变时,它将是一个接近的数字,但有多近?该数字似乎并不完全是连续的.如果我这样做,ps aux | grep apache我会得到相当多的过程:

Linux如何选择下一个号码?前几个PID仍在运行,以及最近打印的PID.apache如何选择重用这些PID?
Mic*_*kis 50
内核在(RESERVED_PIDS,PID_MAX_DEFAULT)范围内分配PID.它在每个命名空间中按顺序执行(不同命名空间中的任务可以具有相同的ID).如果范围用尽,则pid赋值包围.
一些相关代码:
for (i = ns->level; i >= 0; i--) {
nr = alloc_pidmap(tmp);
if (nr < 0)
goto out_free;
pid->numbers[i].nr = nr;
pid->numbers[i].ns = tmp;
tmp = tmp->parent;
}
Run Code Online (Sandbox Code Playgroud)
static int alloc_pidmap(struct pid_namespace *pid_ns)
{
int i, offset, max_scan, pid, last = pid_ns->last_pid;
struct pidmap *map;
pid = last + 1;
if (pid >= pid_max)
pid = RESERVED_PIDS;
/* and later on... */
pid_ns->last_pid = pid;
return pid;
}
Run Code Online (Sandbox Code Playgroud)
请注意,内核上下文中的PID不仅仅是int标识符; 相关结构可以在/include/linux/pid.h.除了id之外,它还包含一个具有该id的任务列表,一个引用计数器和一个用于快速访问的散列列表节点.
PID在用户空间中不出现顺序的原因是因为内核调度可能会在进程fork()调用之间分配进程.事实上,这很常见.
chi*_*oro 10
我宁愿假设你看的行为来自另一个来源:
好的Web服务器通常有几个流程实例来平衡请求的负载.这些过程在池进行管理,并且每个请求进来时分配给特定的要求.为了优化性能的Apache可能是相同的处理分配给一束来自同一客户端的顺序请求.在一定数量的请求之后,进程终止并创建一个新进程.
我不相信linux中按顺序为多个进程分配了相同的PID.
至于你说的是,新的PID是要去接近最后一个,我想Linux的简单分配每个过程的最后一个PID + 1,但也有流程雨后春笋般冒出来,并通过应用程序和系统程序而终止所有后台的时间,从而你无法预测接下来启动的apache进程的确切数量.
除了这个,你应该不使用有关PID分配作为东西你实现基本任何假设.(另见sanmai的评论.)
PID 在大多数系统上是顺序的.您可以通过在闲置计算机上自己启动多个进程来查看.
例如,使用向上箭头历史记录调用重复运行打印自己的PID的命令:
$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 15 19:32 /proc/self -> 21491
$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 15 19:32 /proc/self -> 21492
$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 15 19:32 /proc/self -> 21493
$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 15 19:32 /proc/self -> 21494
Run Code Online (Sandbox Code Playgroud)
不要依赖于此:出于安全原因,有些人运行内核,花费额外的CPU时间来随机选择新的PID.