Linux内核编译

全命令行操作的挑战

Posted by Nathaniel on 2017-03-24

Linux内核编译

缘由

最近在学操作系统,(名为操作系统实为Linux内核)。都说程序员的学习、提高在于实践,实践才能出真知。所以,不来实际操作一下,感受一下Linux内核的魅力,怎么好意思说自己了解Linux操作系统。

准备工作

当然我们不能凭空地就开始编译Linux内核,巧妇难为无米之炊,以下是进行Linux内核编译前需要的准备工作:

搭建一个Linux运行环境

当然我们也可以从基于BSD的macOS、甚至是Windows下编译Linux内核,但是那样的话会有数不清的困难。相比较处理这些困难,我认为我们应该把精力投入主要的目标上去,毕竟一个人的精力是有限的。因此推荐你使用一个虚拟机来搭建一个Linux运行环境。

由于对RedHat公司的特殊好感,我使用了Fedora 25 Server Edition,当然你可以使用任何其他的Linux发行版,由于发行版的不同可能会在部分命令上有细微的差别,但是总体的思路都是一样的。

虚拟机软件的话,推荐你使用Oracle公司开发的小巧而免费的VirtualBox

了解一些基础的Linux命令

虽然说了解这些命令不是必须的,但是没有它们你在Linux下,尤其是没有GUI的Server Edition的Linux下,你将会寸步难行。因此这里有一些常用的bash命令以供参考:

命令 功能
cd 打开某个目录 cd .. 可以返回到上级目录
ls 显示当前目录下所有的非隐藏的文件
./executable 执行某个可执行的二进制文件
cp 复制 cp /path_a/a /path_b/ 表示把path_a下的a复制到path_b下去
mv 移动 同上,操作变为移动
man 查看帮助 man xxx 可以查看 xxx的使用方法,不过都是英文的,需要一些英文功底
tab键 自动补全用,可以在输入长文件名时自动补全该文件名(无名称相似的文件的情况下)
差不多一下午的空闲时间

Linux内核是一个巨大的项目,编译它需要大量的时间,中途而停止不是一个好习惯。当然你可以在编译的过程中干一些其他有意义的事情(比如学习线性代数?😄)

一台用于运行以上环境的计算机

什么?你说你没有计算机。那么要想学好计算机科学,首先你需要找到一台可供你支配的计算机。

开始工作

闲话少说,来开始工作吧,这里假设你已经有了一个可以允许的Linux系统了。接下来就是实际的工作步骤了。

获取Linux系统源码

习惯上,我们喜欢把源代码文件放置到/usr/src/目录下,因此便有了下面的命令

cd /usr/src/
wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.9.16.tar.xz

在这里,我选择了我编译时最新的内核源码版本4.9.16,你当然可以选择任何你想要编译的版本。

解压源码

获取到的源代码是一个压缩包,压缩包的格式是tar.xz,可能有些人会苦恼了,以前见过的压缩包都是.rar``.zip结尾的,从来没有见过tar.xz结尾的压缩包,这该怎么解压呢?是不是得去下载一个类似Winrar的解压软件?别急,Linux自带了解压tar.xz的软件只需使用下面这行命令即可

tar -xvJf linux-4.9.16.tar.xz

紧接着,你就会看到一串文字闪过,当它不再动的时候,就说明解压完成了

解压完了,自然好奇心浓重的我们应该进去一探究竟,输入下面这条命令进入解压后的文件夹

cd linux-4.9.16.tar.xz

文件夹里面都什么呢?显然都是Linux内核的源代码,(好吧源代码压缩包解压后不是源代码还能是什么。。).c .h后缀的文件都是源代码文件。

开始编译

看到这里大家可能有点兴奋了,终于要开始编译了!别着急,磨刀不误砍柴功,我们先来简要了解一下Linux下程序编译的过程:

Linux源码编译至程序需要下面三个步骤

(1)Configure

Configure指令通常用于为在你所使的特定操作系统下做编译的准备工作,通常用于检查该程序编译所需的库是否都已经在系统中存在,以及确定编译器所在的位置等。同时使用程序作者提供的Makefile.in生成下一步需要使用的Makefile

(2)Make

这一步进行实际的编译工作,根据Makefile中的内容对众多源代码文件进行对应的编译、链接操作。这步操作生成了实际的二进制可执行文件

(3)Make Install

生成二进制文件后,显然需要将其放置到特定的目录下。Make Install命令便会将前一步所生成的二进制文件及其文档等移动至目标目录下。

真正的开始编译

显然编译Linux内核也符合上述三个步骤,Linux内核项目由于体积巨大,Configure过程由手工实现将会非常耗时,因此Linux内核提供了多种Configure方式。我采用了Make menuconfig的模式,通过一个古典的GUI 菜单的方式,实现了Configure的过程。命令如下:

make menuconfig

当然,一个友情提示,这一步可能会提醒你缺少libncurses libncurses-devel这样的库,你只需要根据你的Linux发行版进行对应的安装操作就可以了。Fedora下的话只需要输入yum install libcurses即可

成功执行make menuconfig指令后会出现一个下面这样的菜单

4.2

接下来使用方向键把光标移动到Save按钮上,按回车键,会出现下面的一个窗口

再次按回车键,会看到一个确认消息

最后使用方向键把光标移动到Exit上退出这个config生成程序

那么我们刚才究竟做了什么呢?我们实际上完成了上面所说的Linux下编译程序的第一步——Configure过程

生成的.config文件,里面就包含了编译Linux内核所有需要配置的选项

也许你要问了?要这么一个.config文件有什么用呢?

那么我要反问你,你对你常用的软件进行过设置吗?

这里的.config文件,实际上和你设置、个性化你所使用的软件是一个道理,就是控制你的程序的行为,Linux内核项目庞大,需要这样的设置、个性化的地方非常多,由于临时修改代码显得不显示而且不优雅,一个.config文件,就完美的解决了这个问题。

真正的真正的开始编译

好吧,如果特别狭义地定义编译的话,实际上现在我们才开始编译Linux内核代码,输入下面的命令:

make

2~3小时过去了。。。接着输入下面的命令

make modules

1~2小时过去了。。。终于编译完成啦!

安装Linux内核

什么?你只说编译内核,可没有说要安装啊?恩,的确是这样,不过,我们怎么检测我们编译是否成功了呢?那就只有安装一下测试看看了。(如果你的Linux下有重要的项目建议就不要安装了)安装起来吧,其实也并没有多难,输入以下指令:

make modules_install
make install

等了很久之后你就会看到安装成功的消息(当然也可能是安装失败的消息。。。)

大功告成

安装完成之后,怎么看新内核能不能用呢?重启一下便知道。哎,没有开始菜单也没有重启按钮怎么办?Linux下都是靠各种指令度日的,输入以下指令:

reboot

然后你就会看到下面的激动的画面了

6.1

Hurrah!安装成功了,用新内核启动吧。

启动之后又纳闷了,怎么查看版本号呢?

输入下面的指令

uname -a

6.2

恩,果然是最新版的内核

题外话

编译过程中,得保证内存和磁盘空间的充足的供应,就我个人来说,就曾经因内存不足(memory exhausted)和磁盘空间已满(disk full)两个问题而导致了两次的编译失败,重新编译甚为痛苦。因此一定要给你的Linux虚拟机分配足够的硬件资源。

另外,有可能Linux系统没有充分利用你提供给它的硬件资源,这时候需要你手工去分配给它,比如:

先输入

df -h

可以查看你磁盘空间的使用情况

输入

pvscan

可以扫描你未分配的磁盘空间情况

那么怎么把它分配给root分区呢?Staroverflow上的一位神人给予了我们答案:

sudo lvextend --size +10G --resizefs /dev/fedora/root

每次输入这条指令,你的root分区大小就会增大10GB,注意你的不同发行版间命令可能会有区别,此命令仅仅适用于Fedora,另外在你执行pvscan之后显示[M GiB / N GiB free],在N>0的情况下才能使用。