概述
第二章其实是非常简单的一章,主要讲了以下两个方面的内容:
- 如何获取源码和编译
- Linux Kernel 有哪些与众不同的特点
对于第一个问题,个人觉得这本书里面的讲解并不是特别的清晰,我在本文中根据自己摸索 出来的一些经验进行了总结,供大家参考。
如何获取内核的源码和编译内核
如何获取源码
获取源码的压缩包(tarball)
获取源码最直接的方式是访问内核的 官方网站,在官网上你可以找到最 新的内核,以及目前的长期维护版本的最近更新版本的压缩包。
很多时候我们需要找到一些官网首页上不存在的版本,比如如果你正在看一本关于内核的书 ,而这本书使用的内核版本现在已经停止开发了,而新的内核版本和书上的版本改动较大难 以理解,这个时候我们可能会需要一个和书本上一模一样的版本。
内核的网站保存了所有的内核版本,虽然你不能在首页上直接找到它,但是你可以通过以下 链接 找到
我们在官方网站上下载到的都是压缩包,旧的版本一般分为 bz2 版本和 gz 版本,而目前 的版本则包括 gz 版本和 xz 版本,建议下载 bz2 或者 xz 版本,因为它们的压缩效果要 好一些。 bz2 和 gz 版本的解压方式书本上有提到,这里不再重复,如果你下载的是 xz 版本可以使用下面的方式解压:
1 | unxz linux-x.y.z.tar.xz |
通过 git 获取最新的版本
前面提到的方式获取到的压缩包比较小,方便下载和拷贝。但是不断的会有新的版本出现, 如果你不想自己不断的打补丁,那么可能需要不断下载压缩包,以获得最新的稳定版本。
如果你不想不断的下载新的压缩包,你可以考虑使用 git 获取最新的稳定版本,有更新的 时候也可以通过git[^1]很方便的进行更新。
如果你想获得最新的稳定版本可以使用下面的命令:
1 | git clone |
你将会得到一个全新的目录 linux-stable。如果你想要更新里面的内容以获取最新的内核 代码,可以通过在 linux-stable 根目录下执行命令来达到目的:
1 | git pull |
git 使得版本控制变得非常的方便,但是由于内核的代码量非常大,如果你的网速不是很理 想,那么这将会是一个非常漫长的等待过程。因此具体使用上面提到的哪一种做法可能因人 而异。
如何编译源代码
有了源代码之后可以编译它给自己的系统安装全新的内核。在网上的资料中提到的编译安装 的方式一般步骤如下:
make menuconfig(或者 make config、 make gconfig、 make xconfig)
make oldconfig
make
sudo make modules_install
sudo make install
上面提到的方式是编译内核的正常方式,但是对于一般初学者来说并不是最佳的方式。
第一步的作用是对内核进行配置, Linux Kernel 的可定制性非常的高, 你可以只编译你 需要的部分得到一个最适合你的机器的内核版本。但是内核的配置其实非常的复杂,无论你 是使用基于终端的 menuconfig 还是图形界面的 gconfig(gtk+)和 xconfig(qt)你都需 要在浩如烟海的配置选项中找出你想要的那些选项。对于一般人来说这是不太可能完成的任 务,一方面配置太多无法找到一一查看,另外就算你有精力一一查看你也不一定能看懂选择 到底是什么意思(很多选项和硬件相关,没有一定基础基本上搞不明白)。
为了减少配置的困难,你可以尝试以下三种选择:
make defconfig
找到当前 Linux 发行版本的 config 文件,然后使用它作为配置文件编译新的内核
make localmodconfig
第一种方式是直接根据你的系统架构选择默认的配置,这个配置一般会得到一个精巧的的 内核版本。但是默认的配置一般式内核维护者给出的配置,因此不一定适合你的电脑,所以 很有可能你编译得到的新的内核无法正常的启动。不过这个方法对于初学者体验如何编译安 装内核来说是一个不错的选择。
第二种方式是使用当前 Linux 发行版本的 config 文件作为你的配置。这个配置文件一 般存在以下三个目录之一:
/boot/ (ubuntu, centos)
/proc/ (arch)
/usr/src/linux/
找到这些文件之后把它拷贝到你下载的内核根目录下改名为 .config 之后使用 make
oldcongig
。一般来说因为新的内核会加入很多新的配置选择,因此你在 make
oldconfig
过程中会遇到很多新的选项需要你选择,此时一般使用默认值就可以了(直接
按 Enter)。
上面的这种方式一般能得到一个可以运行的的内核。不过出于兼容各种硬件的考虑,发行版 本的配置一般会包含非常多的模块,所以你得到的内核可能会比较臃肿。
第三种方式其实是第二种方式的一个变种,如果你直接在下载的内核源码根目录下面执行
make localmodconfig
,那么相关的脚本会使用找到当前发行版本的配置文件作为蓝本,
然后通过 lsmod 命令找到目前使用了哪些模块,之后选择这些模块的相关配置选项,取消
其他的选项,这样一来你会得到一个较小而且能用的版本。
这种方式可以说是较为可行的一种方式,不过因为它是根据当前系统正在使用的模块来进行
选项设置的,所以如果你当前没有用到某一模块,那么你编译的新内核讲不会包含该模块,
比如你当时没有插入 U 盘那么新的内核可能无法使用 U 盘。 为了解决这个问题你可以首
先手动使用 lsmod
找到目前系统使用的模块并把输出结构保存下来,然后修改这个输出
文件,增加你需要的模块(比如 U 盘驱动),最后把你修改过的模块列表作为参数传递给
make localmodconfig
。具体的方式可以参考下面这个链接
其他小提示:
并不是所有的内核版本都能在你的电脑上正常的运行起来,所以如果你的电脑不能够 正常的运行你编译好的内核版本,你可以考虑换一个内核版本试试。
不要使用 /usr/src 目录作为你的源码编译目录。
编译内核的第一步——配置之前,你可能需要安装一些额外的包才能正常的使用 make meneconfig, make gconfig。不同的发行版本一般不一样,你可以在网上查找。(一 般是 ncurses 的头文件或者 gtk+ 和 qt 的头文件)。
一般的发行版本会有一个软件包帮你安装所有需要工具包(比如:ubuntu 的 kernel-package 和 centos 的 kernel-devel)。
使用 make -jn 会比 直接 make 快很多,n 一般是 CPU 核心数的两倍。
最后推荐一本关于内核的书籍 《Linux Kernel in a Nutshell》,中文名字叫 做《Linux 内核技术手册》。这本书英文版网上可以免费下载,书很薄读起来非常的轻松。 这本书涉及到内核编译的方方面面,虽然已经比较老了,但是仍然是一本值得一读的书。
Linux 内核的特性
Linux 内核作为一个庞大的软件项目(据说有 1000+ 万行),没有一点自己的个性说不过 去。那么 Linux 内核到底包括哪些比较另类(相对于我们写的用户空间程序来说)特点呢 ?
- 不使用 C 函数库,当然也就不会包含标准的 C 头文件
- 用 GNU C 编写而成
- 缺少内存保护机制
- 很难进行浮点运行
- 每个进程都有一个固定大小的内核栈
- 需要着重考虑同步和并发问题
- 可移植性对内核非常重要
这些特点书本上有非常详细的讲解,这里不再重复。值得一提的是第二点,大部分软件开发 都希望迎合标准(使用 ANSI C 或者 C89、C99 标准)而 Linux 内核却使用 GNU C 编写, 我想这或多或少和 GNU 与 Linux 之间的深厚渊源有点关系。 由于 Linux 内核是使用 GNU C 编写,里面使用了大量标准 C 中不存在的用法,除了书上提到的那些以外我在阅读源码 的时候也多少遇到过一些,我把它们整理在了 《C 语言的趣味用法》这篇博 文之中,有兴趣的可以看看。
[^1]: git 是一种新型的版本控制器,关于 git 的更多介绍可以访的 官网。