Linux如何确定下一个PID?
Linux如何确定下一个将用于进程的PID? 这个问题的目的是为了更好地理解Linux内核。 不要害怕发布内核源代码。 如果按顺序分配PID,Linux如何填补空白? 到底会发生什么?
例如,如果我从Apache运行一个PHP脚本来执行<?php print(getmypid());?>
在刷新时打印出相同的PID几分钟。 这段时间是apache接收多less个请求的函数。 即使只有一个客户端,PID最终也会改变。
当PID改变时,它将是一个接近的数字,但有多接近? 这个数字看起来并不完全是连续的。 如果我做一个ps aux | grep apache
ps aux | grep apache
我得到了相当数量的进程:
Linux如何select下一个数字? 前几个PID仍在运行,以及最近打印的PID。 apache如何select重用这些PID?
内核在(RESERVED_PIDS,PID_MAX_DEFAULT)范围内分配PID。 它在每个名称空间中按顺序进行(不同名称空间中的任务可以具有相同的ID)。 如果范围耗尽,pid分配将环绕。
一些相关的代码:
里面的alloc_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; }
alloc_pidmap()
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; }
请注意,内核环境中的PID不仅仅是int
标识符, 相关的结构可以在/include/linux/pid.h
find。 除了id之外,它还包含具有该id的任务列表,引用计数器和用于快速访问的散列列表节点。
在用户空间中不会出现PID的原因是因为内核调度可能会在进程的fork()
调用之间分叉一个进程。 事实上,这很常见。
我宁愿假设你所看到的行为源于另一个来源 :
良好的Web服务器通常有几个stream程实例来平衡请求的负载。 这些进程在一个池中进行pipe理,并在每次请求进入时分配给某个请求。为了优化性能,Apache可能会将相同的进程分配给来自同一客户端的一系列连续请求。 在一定数量的请求之后,进程终止并创build一个新进程。
我不相信有多个进程按顺序被linux分配了相同的PID。
正如你所说,新的PID将接近最后一个,我猜Linux只是给每个进程分配最后一个PID + 1。但是有进程在应用程序和系统程序中一直在后台popup和终止,因此,你无法预测下一步开始的Apache进程的确切数量。
除此之外,你不应该使用任何关于PID分配的假设作为你实现的东西的基础。 (另见sanmai的评论。)
在大多数系统中,PID 是连续的 。 你可以看到,通过自己在闲置机器上启动几个进程。
例如,使用向上箭头历史logging来重复执行打印自己的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
不要依赖于这个:出于安全原因,一些人运行内核花费额外的CPU时间来随机select新的PID。
PID可以随机分配。 有很多方法可以实现这一点。