《Linux内核修炼之道》——2.2 编译内核

简介:

本节书摘来自异步社区《Linux内核修炼之道》一书中的第2章,第2.2节,作者:华清远见嵌入式培训中心 任桥伟著,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.2 编译内核

Linux内核修炼之道
2.2.1 准备工作
虽然与配置内核相比,编译内核所做的工作要少得多,但是在正式编译之前,我们仍需要做一些必要的准备。

1.需要了解的基础知识
首先我们需要了解系统中与编译过程有关的目录及文件。

/boot/vmlinuz-< version >:用于启动的压缩内核镜像。
/boot/system.map-< version >:存储内核符号表。
/boot/initrd.img-< version >:一个镜像文件,类似ramdisk(initrd的全称就是initial ramdisk),它将一些驱动程序和命令工具打包到img里,比如sisc_mod、ext3、sd_mod等模块和insmod、nash等命令,然后在开机的时候在内存里开辟一段区域,释放到那里运行。
它的作用是,在没有mount根分区(/)以前,系统要执行一些操作,比如挂载scsi驱动,此时就把initrd释放到内存里,作一个虚拟的/,然后执行其根目录下的脚本,运行insmod等命令加载模块。
/boot/grub/menu.lst:GRUB的配置文件(不同的发行版中它可能位于不同位置)。
/lib/modules/:该目录包含了内核模块(包括系统自带的和自己编译的)及其他文件,不同的子目录由内核版本号来区分。
/lib/modules/< kernel-version >/build/:存放编译新模块所需的文件,包括了Makefile、.config、module.symVers(模块符号信息)以及内核头文件等。
/lib/modules/< kernel-version >/kernel/:存放模块的ko文件。
/lib/modules//modules.alias:模块别名定义,模块加载工具使用它来加载相应的模块。
/lib/modules/< kernel-version >/modules.dep:定义了模块间的依赖关系。
/lib/modules/< kernel-version >/modules.symbols:标识符号属于哪个模块。
2.下载内核源码压缩包
需要注意下载bz2格式的压缩包时,需要安装bzip2工具进行解压。

3.获取相关补丁
如果需要的某些特性并没有被现有内核支持,则需要去获取相关的补丁。比如,为了使内核支持图形化的启动界面,我们可能要用到bootsplash工具。bootsplash项目的网站http://www.bootsplash.org/上提供了针对很多内核版本的补丁供下载。

4.构建编译环境
编译内核需要用到一系列的工具,在编译之前,我们需要确保它们已经被安装。下面是一些Debian和Ubuntu发行版上用到的工具包。

modutils:模块工具。
kernel-package:包括了make-kpkg等工具。
patch:如果不需要为内核打补丁,可以不安装patch工具包。
build-essential:提供了C/C++的编译环境,包括了gcc、make等工具。
5.备份
当修改内核时,我们必须准备一个能够启动的备用内核。实现该目的的一种方式是通过配置Linux引导程序(LILO或GRUB)以允许用户选择启动的内核映象,其中之一是从未修改过的内核的备份。

2.2.2 如何为内核打补丁
通过打补丁的方法升级内核版本,可以不用下载整个源代码。针对每个内核版本的补丁文件可以在ftp.kernel.org上面获得,我们的问题是应该选择哪个补丁文件,一个补丁又到底应该打在哪个版本的内核上。

下面的内容简单介绍了如何应用与卸载补丁,详细的内容也可以查看内核文档Document/applying-patchs。

1.什么是补丁
一个补丁就是一个文本文档,由diff工具创建,它存放了两个不同版本的源代码之间的差异。为了正确地应用一个补丁,我们需要知道这个补丁文件是以哪个版本为基础产生出来的,以及它将把目前的源代码变化到什么新的版本,简单地说,就是需要清楚产生这个补丁文件的两个源码版本的情况。

2.如何打补丁和卸载补丁
patch工具可以用于打补丁和卸载补丁。内核的补丁是相对于保存内核源码的父目录而生成的,这就意味着,补丁文件中的文件路径包含了内核源码存放目录的名字(比如linux-2.6.23/,或者像是“a/”和“b/”之类的其他名字)。但是很可能我们本地系统上的内核源码存放目录和补丁中不匹配,为了解决这个问题,我们需要切换到自己的源码目录,并且在执行patch命令的时候加上“-p1”参数,这样就会去掉补丁文件中路径的第一个分量。比如:

# cd /usr/src/linux
# patch –p1 < ../patch-x.y.z

为了卸载一个以前打上的补丁,需要使用“-R”参数。

# patch –R –p1 < ../patch-x.y.z

3.如何利用补丁升级内核版本
考虑这样的几个场景:将内核从2.6.23升级到2.6.24;将内核从2.6.23.8升级到2.6.24.6;将内核从2.6.23.6升级到2.6.23.8。不管处于哪种场景,打补丁时要谨记的一点是:内核的补丁文件都是以2.6.x(基础稳定版basic stable,2.6.x.y是稳定版stable)为基础发布的。下面对这3种场景的打补丁过程分别进行介绍。

(1)将内核从2.6.23升级到2.6.24。这种情况,可直接使用补丁文件patch-2.6.24。

# patch –p1 < ../patch-2.6.24

因为下载得到的补丁文件通常是使用gzip或bzip2压缩的格式,所以使用前还要将其解压生成patch-x.y.z文件。不过,我们也可以不用解压,使用下面的命令形式:

# bzcat ../patch-2.6.24.bz2 | patch -p1 //bz2格式
# zcat ../patch-2.6.24.gz | patch -p1   //gz格式

(2)将内核从2.6.23.8升级到2.6.24.6。这种情况下,我们需要将升级的过程分解为几个步骤,首先将2.6.23.8退回到2.6.23,然后再升级到2.6.24,最后升级到2.6.24.6。

# bzcat ../patch-2.6.23.8.bz2 | patch -p1 –R
# bzcat ../patch-2.6.24.bz2 | patch -p1
# bzcat ../patch-2.6.24.6.bz2 | patch -p1

(3)将内核从2.6.23.6升级到2.6.23.8。这种情况下,我们同样需要将升级过程分解,首先将2.6.23.6退回到2.6.23,然后再升级到2.6.23.8。

# bzcat ../patch-2.6.23.6.bz2 | patch -p1 –R
# bzcat ../patch-2.6.23.8.bz2 | patch -p1

4.patch的替代工具
除了patch之外,也有其他的用来打补丁的工具,比如interdiff、ketchup等。

2.2.3 编译步骤
下面是针对2.6内核的通用的编译步骤。

(1)下载源码并解压。

虽然我们可以将内核源码存放在任何自己找得到的地方,但通常还是会将内核源码下载到/usr/src目录并解压(Linus本人说不要解压到这个目录)。

# cd /usr/src
# wget ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2 
# tar jxvf linux-2.6.23.tar.bz2

(2)如果需要的话,下载补丁。

(3)进入刚刚解压的内核源码目录。

# cd /usr/src/linux-2.6.23

(4)如果需要的话,为内核打补丁。

(5)配置内核。

# make menuconfig

(6)编译内核。

# make

(7)安装内核模块。将所有编译得到的内核模块复制到/lib/modules/< kernel-version >/目录下面。

# make modules_install

(8)安装内核。

# make install

make install主要完成了3个工作。

复制生成的内核映像到/boot目录。在内核编译完成后,源码树目录arch/i386/boot/中会生成一个bzImage文件,该文件被复制到/boot目录并重命名为vmlinuz-2.6.23。
生成initrd-< kernel-version >.img文件。
配置引导程序(GRUB或LILO)。
(9)重启进入新内核。

2.2.4 文档的编译
内核源码树的Documentation/目录下面有大量的文档,它们是内核最好的参考资料,对于我们学习内核有着重要的意义。我们可以使用下面的一些命令生成指定格式的文档。

# make htmldocs        //生成HTML文件
# make pdfdocs        //生成PDF文件
# make psdocs         //生成Postscript文件
# make mandocs        //为Kernel API生成man手册
# make installmandocs //将Kernel API手册页安装到man程序能够找到的目录中

执行make htmldocs/pdfdocs/psdocs之后,在Documentation/DocBook/目录下,会生成一些很重要的文档:

kernel-api:内核开发的API手册。
kernel-locking:内核加锁的HOWTO文档。
kernel-hacking:内核开发的一些注意事项。
usb:USB Host端的API手册。
gadget:Usb Device端的API手册。
2.2.5 编译小技巧
下面是一些内核编译过程中可以使用的小技巧。

(1)屏蔽编译信息。

# make > /dev/null

(2)加速编译过程。

可以使用“-j< n >”参数,其中n = 2 * CPU的个数,对于一般的单CPU系统,通常用是使用“-j2”参数,为编译过程分配两个任务,这样在进行磁盘I/O操作时候,CPU就不会空闲了。

# make –j2 > /dev/null

(3)使用verbose模式,将每一步执行的命令都打印出来,并重定向到一个文件中去,这样以后可以方便地查找模块之间的依赖关系。

# make V=1 > ~/bak.txt

(4)使用ccache提高编译速度。使用ccache时,需要更改源码树根目录下面的Makefile文件,在CC和HOSTCC变量的定义前添加ccache。

CC      = ccache $(CROSS_COMPILE)gcc
HOSTCC  = ccache gcc
相关文章
|
14天前
|
Linux C语言
Linux内核队列queue.h
Linux内核队列queue.h
|
1月前
|
Shell Linux C语言
【Shell 命令集合 系统设置 】⭐Linux 卸载已加载的内核模块rmmod命令 使用指南
【Shell 命令集合 系统设置 】⭐Linux 卸载已加载的内核模块rmmod命令 使用指南
29 1
|
7天前
|
算法 Linux 调度
深入理解Linux内核的进程调度机制
【4月更文挑战第17天】在多任务操作系统中,进程调度是核心功能之一,它决定了处理机资源的分配。本文旨在剖析Linux操作系统内核的进程调度机制,详细讨论其调度策略、调度算法及实现原理,并探讨了其对系统性能的影响。通过分析CFS(完全公平调度器)和实时调度策略,揭示了Linux如何在保证响应速度与公平性之间取得平衡。文章还将评估最新的调度技术趋势,如容器化和云计算环境下的调度优化。
|
12天前
|
算法 Linux 调度
深度解析:Linux内核的进程调度机制
【4月更文挑战第12天】 在多任务操作系统如Linux中,进程调度机制是系统的核心组成部分之一,它决定了处理器资源如何分配给多个竞争的进程。本文深入探讨了Linux内核中的进程调度策略和相关算法,包括其设计哲学、实现原理及对系统性能的影响。通过分析进程调度器的工作原理,我们能够理解操作系统如何平衡效率、公平性和响应性,进而优化系统表现和用户体验。
20 3
|
19天前
|
负载均衡 算法 Linux
深度解析:Linux内核调度器的演变与优化策略
【4月更文挑战第5天】 在本文中,我们将深入探讨Linux操作系统的核心组成部分——内核调度器。文章将首先回顾Linux内核调度器的发展历程,从早期的简单轮转调度(Round Robin)到现代的完全公平调度器(Completely Fair Scheduler, CFS)。接着,分析当前CFS面临的挑战以及社区提出的各种优化方案,最后提出未来可能的发展趋势和研究方向。通过本文,读者将对Linux调度器的原理、实现及其优化有一个全面的认识。
|
19天前
|
Ubuntu Linux
Linux查看内核版本
在Linux系统中查看内核版本有多种方法:1) 使用`uname -r`命令直接显示版本号;2) 通过`cat /proc/version`查看内核详细信息;3) 利用`dmesg | grep Linux`显示内核版本行;4) 如果支持,使用`lsb_release -a`查看发行版及内核版本。
36 6
|
22天前
|
Linux 内存技术
Linux内核读取spi-nor flash sn
Linux内核读取spi-nor flash sn
18 1
|
28天前
|
存储 网络协议 Linux
【Linux 解惑 】谈谈你对linux内核的理解
【Linux 解惑 】谈谈你对linux内核的理解
23 0
|
1月前
|
存储 Linux Shell
【Shell 命令集合 系统设置 】Linux 显示Linux内核模块的详细信息 modinfo命令 使用指南
【Shell 命令集合 系统设置 】Linux 显示Linux内核模块的详细信息 modinfo命令 使用指南
26 0
|
1月前
|
Shell Linux C语言
【Shell 命令集合 系统设置 】⭐Linux 向内核中加载指定的模块 insmod命令 使用指南
【Shell 命令集合 系统设置 】⭐Linux 向内核中加载指定的模块 insmod命令 使用指南
31 0