Linux内核如何编译自己?
当我在我的机器上安装Linux系统时,我不太了解Linux内核的编译过程。
以下是一些使我困惑的事情:
- 内核是用C编写的,但是如果没有安装编译器,内核是如何编译的呢?
- 如果在编译内核之前在我的机器上安装了C编译器,那么编译器本身如何在没有安装编译器的情况下进行编译?
我感到困惑了几天,感谢回应。
你的Linux机器的第一轮二进制文件是build立在其他Linux机器上的(可能)。
第一个Linux系统的二进制文件是build立在其他平台上的。
该计算机的二进制文件可以追溯到在另一个平台上构build的原始系统。
…
推得这么远,你会发现用更原始的工具构build的编译器,而这些工具又build立在主机以外的机器上。
…
继续推动,你发现计算机内置,使他们的指示可以通过设置机器的前面板上的开关进入。
非常酷的东西。
规则是“构build工具来构build工具…”。 非常像运行我们的物理环境的工具。 也被称为“通过bootstraps拉你自己”。
我认为你应该区分:
编译 ,v:使用编译器来处理源代码并生成可执行代码[1] 。
和
安装 ,v:连接,设置或准备使用[2] 。
编译从源代码生成二进制可执行文件。 安装只是将这些二进制可执行文件放在正确的位置以便稍后运行它们。 所以,如果二进制文件可用,安装和使用不需要编译。 像“厨师”和“服务”一样思考“编译”和“安装”。
现在,你的问题:
- 内核是用C编写的,但是如果没有安装编译器,内核是如何编译的呢?
内核不能在没有编译器的情况下编译,但可以从编译的二进制文件安装 。
通常,当您安装操作系统时,您将安装预编译的内核(二进制可执行文件)。 它是由其他人编译的。 只有当你想自己编译内核时,你需要源代码和编译器,以及所有其他工具。
即使在像gentoo这样的“基于源代码”的发行版中,您也可以从运行一个已编译的二进制文件开始
所以,你可以在不编译内核的情况下过完整个人生,因为你有他人编译的内核。
- 如果在编译内核之前在我的机器上安装了C编译器,那么编译器本身如何在没有安装编译器的情况下进行编译?
如果没有内核(OS),编译器将无法运行。 所以必须安装一个编译的内核来运行编译器,但是不需要自己编译内核。
再次,最常见的做法是安装编译器的编译二进制文件,并使用它们编译其他任何东西(包括编译器本身和内核)。
现在,鸡和鸡蛋的问题。 第一个二进制文件是由别人编译的…请参阅dmckee的优秀回答。
描述这个现象的术语是bootstrapping ,这是一个有趣的概念。 如果你想到embedded式开发,很明显,需要软件的很多设备,比如闹钟,微波炉,遥控器,都不足以编译自己的软件。 实际上,这些types的设备通常没有足够的资源来远程执行像编译器那样复杂的任何操作。
他们的软件是在台式机上开发的,一旦编译完成就复制。
如果这种事情让你感兴趣的话,那么从我脑海中浮现出来的一篇文章是: “信任信任的思考” ( pdf ),这是一个经典而有趣的阅读。
内核不会自行编译 – 它由用户空间中的C编译器编译。 在大多数CPU架构中,CPU在特殊寄存器中有许多位,代表当前正在运行的代码有什么特权。 在x86中,这些是代码段 (CS)寄存器中的当前特权级别位(CPL)。 如果CPL位是00,则代码被称为在安全环0中运行,也称为内核模式 。 如果CPL位是11,则该代码被称为在安全环3中运行,也称为用户模式 。 另外两种组合01和10(分别是安全环1和2)很less使用。
在用户模式和内核模式下哪些代码可以和不可以做的规则是相当复杂的,但足以说,用户模式已经严重降低了特权。
现在,当人们谈论操作系统的内核时,他们指的是操作系统代码中以高级特权运行于内核模式的部分。 一般来说,由于安全原因,内核作者试图保持内核尽可能小,以便不需要额外特权的代码不具有它们。
C编译器就是这样一个程序的一个例子 – 它不需要内核模式提供的额外权限,所以它像大多数其他程序一样以用户模式运行。
在Linux的情况下,内核由两部分组成:内核的源代码和编译的内核可执行文件。 任何具有C编译器的机器都可以将内核从源代码编译到二进制映像中。 那么问题是如何处理二进制图像。
在新系统上安装Linux时,通常需要从物理介质(例如CD DVD)或networking上安装预编译的二进制映像。 BIOS将从媒体或networking加载内核引导加载程序的二进制映像,然后引导加载程序将(内核的二进制映像)安装到您的硬盘上。 然后,当你重新启动时,BIOS从硬盘加载内核的启动加载程序,启动加载程序将内核加载到内存中,然后closures并运行。
如果你想重新编译自己的内核,那有点麻烦,但是可以做到。
哪一个在那里? 鸡还是鸡蛋?
自从恐龙时代以来,鸡蛋一直存在。
一些人认为鸡只是大兽的后代,一切都是混淆的。长话短说:技术(鸡蛋)是在现有产品(鸡)之前存在的,
你需要一个内核来构build一个内核,也就是说你需要build立一个内核。
第一个内核可以是任何你想要的东西(最好是可以创build你想要的最终产品的东西)
Bran的内核开发的这个教程告诉你开发和构build一个小的内核,然后你可以用你select的虚拟机进行testing。
含义:你在某处编写和编译内核,然后在一个空的(无OS)虚拟机上读取它。
这些Linux安装会发生什么,遵循相同的想法,增加了复杂性。
这不是乌龟一路下来。 就像你说的那样,你不能在运行该操作系统的系统上编译以前从未编译过的操作系统。 同样,至less编译器的第一个版本必须在另一个编译器上完成(通常还有一些后续版本,如果第一个编译结果不能够编译自己的源代码)。
我认为最早的Linux内核是在Minix框中编译的,尽pipe我对此没有把握。 GCC在当时是可用的。 许多操作系统的早期目标之一就是运行一个足够好的编译器来编译自己的源代码。 进一步说,第一个编译器几乎肯定是用汇编语言编写的。 第一个汇编程序是由那些不得不用原始机器码写的穷人编写的。
你可能想看看Linux From Scratch项目。 实际上,您在书中构build了两个系统:一个“临时系统”,构build在您自己没有构build的系统上,然后是构build在临时系统上的“LFS系统”。 本书的写作方式,实际上是在另一个Linux机器上build立临时系统,但是理论上你可以用它来在一个完全不同的操作系统上构build临时系统。
如果我正确理解你的问题。 内核现在不是“编译自己”。 目前大多数Linux发行版都是通过linux Live CD提供系统安装。 内核从CD加载到内存中,并像正常安装到磁盘一样运行。 在你的系统上运行一个linux环境,很容易就可以把必要的文件提交到你的磁盘上。
如果你在谈论引导问题, dmckee总结起来相当不错。
只是提供另一种可能性