Unix 中交换进程的主要用途是什么?
Swapper 进程的 PID 为 0,我猜它是第一个加载的进程。有人能更详细地解释一下这个问题吗?
答案1
自 1990 年代以来,它不再是一个交换过程,自 1970 年代以来,交换实际上就没有被使用过。
Unices 很久以前就停止使用交换了。几十年来,它们一直是按需分页操作系统——自 System V R2V5 和 4.0BSD 以来。交换器进程曾经用于执行进程交换操作。它曾经交换整个流程——包括所有内核空间进程的数据结构 — 移出到磁盘并再次交换回来。它会定期被内核唤醒,并扫描进程表以确定哪些已交换出去并准备运行的进程可以交换进来,哪些已交换进来但处于休眠状态的进程可以交换出去。任何 20 世纪 80 年代的 Unix 教科书都会更详细地介绍这一点,包括交换算法。但这与按需分页的 Unix 基本无关,尽管它们保留了旧的交换机制好几年。(例如,BSD 非常努力地避免交换,转而采用分页。)
进程 #0 是系统中的第一个进程,由内核手工创建。它fork()
是进程 1,第一个用户进程。除此之外它还做什么取决于实际的 Unix 操作系统。如前所述,FreeBSD 5.0 之前的 BSD 保留了旧的交换器机制,进程 #0scheduler()
在完成系统初始化后,只是简单地放入内核中的交换器代码(函数)。System V 大致相同,只是进程 #0 是常规名称,sched
而不是swapper
。(名称几乎是任意选择。)事实上,大多数(可能所有)Unices 都有一个(基本上未使用的)旧交换器机制,作为进程 #0 保留。
传统上,Linux 与 Unices 有所不同,因为进程 #0 是空闲进程,运行cpu_idle()
。它什么都不做,陷入无限循环。它存在,所以有总是准备被安排的任务。
即使是这样的描述也已经过时了。20 世纪 80 年代末和 90 年代初是多线程操作系统的出现,因此进程 #0 变得简单系统进程在旧的单线程 Unices 世界中,只有通过fork()
启动进程才能获得单独的执行流来执行连续的内核任务。因此,所有内核任务(例如,在 FreeBSD 系统上,、、、、、等等)都是低编号进程,由进程vmdaemon
# 0在启动后启动。在多线程 Unices 中,为完全在内核空间中运行的程序创建全新的进程上下文是没有意义的,它本身不需要地址空间、文件描述符表等。因此,所有这些任务都变成了(本质上)线程,共享单个系统进程的地址空间。 pagedaemon
pagezero
bufdaemon
syncer
ktrace
fork()
fork()
ìnit
在此过程中,一些 Unices 最终放弃了旧的交换机制,他们尽最大努力避免使用它。while(1) tsleep(…);
例如,OpenBSD 的初始化代码现在只是陷入循环,没有任何交换机制。
所以如今Unix 上的进程 #0 是系统进程,实际上包含了许多内核线程执行许多操作,包括从页面输出操作到文件系统缓存刷新和缓冲区清零,再到没有其他操作可运行时的空闲状态。
答案2
进程 0 是一个特殊进程(称为交换进程或空闲进程),它在系统空闲时运行,即没有其他进程被调度。它是唯一可以调用系统idle()
调用的进程。
这是第一个被生成的进程,然后创建init
(PID 1)来启动其他进程。
root 1 0 /sbin/init
您也可以检查man idle
。
也可以看看:理解 Linux 内核 – 进程调度
答案3
原因是历史原因和程序原因。如您所说,如果没有其他任务可运行,则空闲任务正在运行。它的优先级最低,因此如果没有其他任务可运行,它就会运行。
程序原因:这大大简化了进程调度,因为您不必关心特殊情况:“如果没有任务可运行会发生什么?”,因为总是至少有一个任务可运行,即空闲任务。您还可以计算每个任务使用的 CPU 时间量。如果没有空闲任务,哪个任务会占用没有人需要的 CPU 时间?
历史原因:在 CPU 能够降压或进入省电模式之前,它必须随时全速运行。如果没有任务可运行,它会运行一系列 NOP 指令。如今,空闲任务的调度通常使用 HLT 指令(暂停)来降低 CPU 的运行速度,从而节省电量。所以现在空闲任务在某种程度上具有某种功能。
在Windows中你可以在进程列表中看到空闲任务,它就是空闲进程。