获取、编译、安装内核
- 1 获取内核源码
- 安装内核源代码
- 何处安装源码
- 使用补丁
- 2 内核源码树
- 3 编译内核
- 减少编译的垃圾信息
- 衍生多个编译作业
- 安装内核
- 启用指定内核作为引导
- 4 内核开发的特点
- 没有libc库
- 头文件
- 没有内存保护机制
- 容积小而固定的栈
1 获取内核源码
在linux内核官方网站http://www.kernel.org,可以获得当前最新版本Linux源码码。如果想找一些老版本的源代码,可以:https://mirrors.edge.kernel.org/pub/linux/kernel/下载。
安装内核源代码
内核压缩以GNU zip(gzip)和bzip2两种形式发布。以bzip2形式发布的Linux内核叫做linux-x.y.z.tar.bz2,这里x.y.z是内核源码的具体版本。如果压缩形式是bzip2,则运行:
tar rvjf linux-x.y.z.tar.bz2
如果压缩形式是GNU的zip,则运行:
tar xvzf linux-x.y.z.tar.gz
何处安装源码
内核源码一般安装在/usr/src/具体linux版本 目录下。不要以root身份对内核进行修改,而应当是,建立自己的主目录。仅以root身份安装新内核,即使在安装新内核时,/usr/src/linux目录都应当原封不动。
使用补丁
在linu内核社区中,补丁是通用语。你可以以补丁的形式发布对代码的修改,也可以以补丁的形式接收其他人所做的修改。内核版本不断更新,增量补丁可以作为版本转移的桥梁。你不在需要下载内核源码的全部压缩,而只需给旧版本打上一个增量补丁,让其旧貌换新颜,更新内核版本。只需运行:
patch-p1 < ../patch-x.y.z
一般来说,一个给定版本的内核补丁总是打在前一个版本上。
2 内核源码树
内核源码树由很多目录组成,而大多数目录又包含更多子目录。源码树的根目录及其子目录如下表:
目录 | 描述 |
---|---|
arch | 特定体系结构的源码 |
crypto | Crypto API |
Documentation | 内核源码文档 |
drivers | 设备驱动程序 |
fs | VFS和各种文件系统 |
include | 内核头文件 |
init | 内核引导和初始化 |
ipc | 进程间通信代码 |
kernel | 像调度程序这样的核心子系统 |
lib | 通用内核函数 |
mm | 内存管理子系统和VM |
net | 网络子系统 |
scrripts | 编译内核所用的脚本 |
security | Linux安全模块 |
sound | 语音子系统 |
usr | 早期用户空间代码 |
在源码树根目录中,COPYING是内核许可证,CREDITS是开发者列表。MAINTAINERS是维护者列表,维护内核子系统和驱动程序。最后,Makefile是Makefile内核的基础
3 编译内核
在编译内核之前,首先你必须配置它。可以配置的各种选项,以CONFIG_FEATURE形式表示,其前缀为CONFIG。例如,对称处理器(SMP)的配置选项为CONFIG_SMP。如果设置了该选项,则SMP启用,否则,SMP不起作用。
这些配置项要么是二选一,要么是三选一。二选一就是yes或no。三选一可以是yes、no或module。module意味着该配置项被选定了,但编译的时候这部分功能的实现代码是以模块(一种可以动态安装的独立代码段)的形式生成。在三选一的情况下,yes表示把代码编译进内核映射中,而不是作为一个模块。
内核提供了各种不同的工具来简化内核配置。最简单的一种是基于文本的命令行工具:
make config
该工具会挨个遍历所有配置项,要求用户选择yes、no或module。
如果该命令不能执行,说明没有安装一些工具,可以根据提示安装,我的需要安装make、gcc、bison、flex
sudo apt-get install make gcc bison flex
这个过程很耗费时间,所以,除非你的工作是按小时计费的,否则你应该多利用基于ncuse编译的图形界面工具。
make menuconfig
或者基于X11的图形工具
make xconfig
或用基于gtk+图形工具
make gconfig
这三种工具将所有配置项分门别类放置,比如按处理器类别和特点,你可以按类移动、浏览内核选项,当然也可以修改其值。
命令:
make defconfig
通过这条命令为你的体系结构创建一个默认的配置。尽管这些默认值有点随意性,但是,如果你从未配置过内核,那就会提供一个良好的开端。
执行完,帮我配置的是x86_64_defconfig。这些配置项会存放在内核代码树根目录下的.config文件中,我们也可修改它,打开看看
再修改过配置文件之后,或者在用旧的配置文件配置新的代码树的时候,应该验证和更新配置:
make oldconfig
一旦内核配置好了,就可以编译它了,执行命令:
make
减少编译的垃圾信息
我们希望在编译时看到错误和警告消息,但对匆匆掠过屏幕的垃圾信息不感兴趣,可以使用如下命令
make > /dev/null
就可以把无用的输出信息重定向到永无返回值的黑洞/dev/null
衍生多个编译作业
多个作业独立并发运行,可以提高处理器系统上的编译过程。默认情况下,make只衍生一个作业。为了可以以多个作业编译内核,使用一下命令:
make -jn
n是要衍生的作业数,在实际中,每个处理器一般衍生一个或者两个作业。例如,在一个双处理器上,可以输入如下命令:
make -j4
安装内核
在内核编译好了之后,还需要安装它。怎么安装就和体系架构以及启动引导工具(boot loader)息息相关了—查阅启动引导工具的说明,按照它的指导将内核映像拷贝到合适的位置,并且按照启动要求安装它。一定要保证随时有一个或两个可以启动的内核,以放新编译的内核出现问题。
安装命令:
sudo make install
模块的安装是自动的,也是独立于体系结构的。以root身份,只要运行:
sudo make modules_install
就可以把所有编译号的模块安装到正确的主目录/lib下
可以看到,编译的内核版本号是5.0.0
同时也列出了还有那个内核
查看现在使用的内核版本
启用指定内核作为引导
输入下列命令将内核作为引导,将数字更改为你自己编译的版本号:
sudo update-initramfs -c -k 5.0.0
跟新一下grub:
sudo update-grub
之后重启即可在启动界面选择需要重启的内核。如果看不到重启选择界面,执行以下操作。
输入命令:
sudo vim /etc/default/grub
注释掉hidden那一行,将timeout更改为较大值,这里改为了10
之后执行
sudo update-grub
重启即可看到下面此单,选择高级选项,进入后选择编译安装好的内核进入即可,
选择我们刚刚编译好的内核,5.0.0,倒数第二个
可以看到是我们编译的内核
4 内核开发的特点
没有libc库
与用户空间的应用程序不同,内核不能链接使用标准C函数库。最主要的原因是对于内核来说,完整的C库太大了,影响速度和大小。
大部分常用的C库函数在内核中都已经得到了实现。比如说操作字符串的函数组就位与lib/string.c文件中。只要包含<linux/string.h>头文件就可以使用。
头文件
内核源代码文件不能包含外部头文件,所说的头文件是指组成内核源代码树的内核头文件。
在没有实现的函数中,最著名的就数printf()函数了。内核代码虽然无法调用printf(),但它可以调用printk()函数。printk()函数负责把格式化好的字符串拷贝到内核日志缓存区上,这样,syslog程序就可以通过读取缓冲区来获取内核信息。
没有内存保护机制
如果一个用户程序试图进行一次非法的内存访问,内核会出现这个错误,发送SIGSEGV,并结束整个进程。然而,如果是内核自己非法访问了内存,那后果就很难控制了。内核中发生的内存错误会导致oops,这是内核中常见的一类错误。
此外,内核中的内存都不分页,也就是说,每用掉一个字节,物理内存就减少一个字节。所以,在你想往内核加入什么新功能的时候,要记住这一点。
容积小而固定的栈
内核栈的准确大小随体系结构而变,但都是两页。每个处理器都有自己的栈