MAX_PROCESS: 系统内最多进程数
MAX_PID: 是2倍的MAX_PROCESS, pid的范围是 [0, MAX_PID)
next_safe: 在 [last_pid, next_safe) 区间内可以取得有效的(未被占用的)pid,初始化为MAX_PID,实际是大于last_pid且值最小的已占用的pid,在一定程度上能减少探测次数优化程序
last_pid: 探测pid的指针
get_pid的总体思路在 [0, MAX_PID) 范围内循环的探测可取得的pid,由于进程在创建后会陆续终结,最后pid的分布会零散。
static int
get_pid(void) {
static_assert(MAX_PID > MAX_PROCESS);
struct proc_struct *proc;
list_entry_t *list = &proc_list, *le;
//静态初始化,只进行一次
static int next_safe = MAX_PID, last_pid = MAX_PID;
//递增last_pid 如果大于有效值,重新从1开始探测(0号进程为idle)
if (++ last_pid >= MAX_PID) {
last_pid = 1;
//必须更新next_safe
goto inside;
}
//基于之前所维护的next_safe 如果last_pid < next_safe,则last_pid是有效的
if (last_pid >= next_safe) {
//last_pid可能是无效的 并且需要重新计算next_safe
inside:
//初始化next_safe为最大值,后续需要计算最小值
next_safe = MAX_PID;
repeat:
le = list;
//遍历proc_list
while ((le = list_next(le)) != list) {
proc = le2proc(le, list_link);
//last_pid被占用
if (proc->pid == last_pid) {
//递增后如果超过当前维护的next_safe,则之前遍历链表对next_safe的维护是无效的
//需要重新遍历链表
if (++ last_pid >= next_safe) {
//注意当超过范围时返回到1进行重新一轮循环
if (last_pid >= MAX_PID) {
last_pid = 1;
}
next_safe = MAX_PID;
goto repeat;
}
}
else if (proc->pid > last_pid && next_safe > proc->pid) {
//如果当前的proc->pid大于last_pid 则可用于跟新next_safe
next_safe = proc->pid;
}
}
}
return last_pid;
}