Linux内核编译与管理

我们说的Linux其实指的就是 内核(kernel)而已。这个内核控制你主机的所有硬件并提供系统所有的功能,所以它非常重要。我们开机的时候就是利用开机管理程序加载这个内核文件来检查硬件,在内核加载适当的驱动程序后,系统才能够顺利运行。

现今的系统由于强调在线升级机制,因此非常不建议自定义内核编译!但是,如果你想将你的Linux安装到USB移动设备,将你的PC安装自己的Linux,想让你的Linux可以驱动你的PC,内核编译就是相当重要的一个任务。

编译前的任务:认识内核与取得内核源代码

内核(kernel)是整个操作系统的最底层,它负责了整个硬件的驱动,以及提供各种系统所需的核心功能。包括防火墙机制、是否支援LVM或Quota等文件系统。如果你的内核不认识某个最新的硬件,那么该硬件也就无法被驱动,当然也就无法使用该硬件。

什么是内核(kernel)?

Kernel

电脑真正在工作的东西其实是 “硬件”,例如数值运算要使用到CPU、储存资料要用到硬盘、图形显示要用到显卡、音频需要声卡、连接Internet需要网卡等等。那么如何控制这些硬件呢?那就是内核的工作了。

你想让计算机进行的工作,都必须要内核支持才行,这个标准不论是LInux还是Windows都一样。

其实内核就是系统上面的一个文件而已,这个文件包含了驱动主机各项硬件的检测程序与驱动模块。在开机流程分析中,这个文件被读入主存储器的时机,当系统读完BIOS并加载MBR内的引导装载程序后,就能够加载内核到内存当中。然后内核开始检测硬件,挂载根目录并取得内核模块来驱动所有的硬件,之后调用 systemd就能依序启动所有系统所需的服务了。

这个内核文件通常被放置在 /boot/vmlinuz-xxx,不过也不见得,因为一台主机上可以拥有多个内核文件,而开机的时候仅能选择一个来加载而已。我们甚至可以在一个distribution上面放置多个核心,然后以这些核心来做成多重开机。

内核模块(Kernel module)用途

既然内核文件都已经包含了硬件检测与驱动模块,那么什么是内核模块?

如果我的内核比较旧,但是我换了新的硬件,这个内核肯定无法识别,而重新编译内核是很麻烦的。为了这个缘故,Linux就开始使用所谓的模块化设置了。即是将一些不常用的类似驱动程序的内容独立出内核,编译成模块,然后,内核可以在系统正常运行的过程中加载这个模块到内核的支持。如此一来,我在不需要更改内核的前提下,只要编译出适当的内核模块,在加载它,Linux就可以使用这个硬件了。模块组放置于 /lib/modules/$(uname -r)/kernel/中。

自制内核-内核编译

内核文件是通过 源码(source code)编译而成的。因为内核是直接被读入主存储器中,所以要将它编译成为系统可认识的文件才行,也就是说,我们要取得内核的源码,然后进行编译。

关于驱动程序:是厂商的责任还是内核的责任

在驱动程序的开发这个工作上来说,应该是属于硬件发展厂商的问题。主要是Linux上面的使用人员实在是少于Windows人员。

更新内核的目的

除了BIOS(或UEFI)之外,内核是操作系统中最早被加载到主存储器的,它包含了所有可以让硬件和软件工作的信息。所以,如果没有搞定核心,系统肯定会有小问题。

内核编译的重点在于 “你的Linux做什么?”,如果没有必要的工作,就不用加在内核当中,这样才能让你的Linux跑的更快更稳健。这也是为什么我们需要编译内核的最主要原因。

Linux内核特色与默认内核对终端用户的角色

Linux内核有几个主要的特色,除了Kernel可以随时、 随各人喜好而改动之外,版本改动次数太频繁也是一个特点。所以,除非你有特殊需求,否则一次编译成功就可以啦!不需要随时保持最新的内核版本,而且也没有必要(便以一次内核要很久。)

对于一般的使用者,由于系统已经将内核编译的相当得相当适合普通用户使用了,因此一般入门的用户基本上不太需要编译内核。

内核编译的可能目的

当然是有需要才回来编译内核啦!

编译内核的时机可以归纳为以下几类:

新功能的需求

我需要新的功能,而这个功能只在新的内核里面才有,为了获得这个功能,只好重新编译我的内核;

原本的内核太过于臃肿

如果你对系统稳定性很要求,对于内核多编译了很多莫名其妙的功能不太喜欢的时候,那么就可以重新编译内核来取消该功能;

与硬件搭配的稳定性

内核也可能没有正确的驱动新的硬件,此时就得重新编译核心来让系统取得正确的模块才好;

其他需求(如嵌入式系统)

你需要特殊的环境需求时,就得自行设计你的内核;

如果为了增加性能来编译内核的话,基本上,效益不大。然而,如果是针对“系统稳定性”来考量的话,那么就有充分的理由来支持你重新编译内核。

如果系统已经运行很久了,而且也没有什么问题,加上我又不想增加冷门的硬件设备,那么建议就不需要重新编译内核。因为重新编译内核的主要目的是“想让系统变得更加稳定”。

由于内核的主要工作是控制硬件,所以编译之前,请先了解硬件设备和主机未来的功能。内核当然是越简单越好啦!

内核的版本

uname -r

Linux内核编译与管理_第1张图片
内核版本

目前CentOS7使用的3.10.x版本为长期维护版本,不过理论上我们也可以升级到后续的主线版本上。

内核源代码的取得方式

基本上,依据我们的distributions去挑选的内核源码主要有:

原本distribution提供的内核源代码文件

全部的CentOS原始SRPM,http://vault.centos.org/;

CentOS 7.1的SRPM,http://vault.centos.org/7.1.1503/;

原本的distribution放出的源码中,包含有他们设定好的默认值,我们也就可以轻易的了解到当初他们是如何选择与内核有关的各项设定项目的参数值,就可以利用这些可以配合我们Linux系统的默认参数加以修改。

取得最新的稳定版内核源代码

Linux的内核目前是由其发明者 Linus Torvalds所属团队在负责维护,其网站上可以找到最新的Kernel信息。

内核官网:https://www.kernel.org/;

保留原本设置:利用patch升级内核源代码

其实每一次内核发布时,除了发布完整的内核压缩文件以外,也会发布该版本与前一版本的差异性补丁(patch)文件,每个内核的patch仅仅是针对前一版本的内核来分析而已;

所以,如果想要从3.10.85升级到3.10.88的话,那么就得要下载 “patch-3.10.86,patch-3.10.87,patch-3.10.88”等文件,然后 依序一个一个的进行patch动作,这个很重要!

同样,如果是某个硬件或非官方机构所发布的patch文件时,你也必须要了解该patch文件所适用的内核版本,然后才能进行patch动作;

在进行完patch动作之后,你可以直接检查一下原本的设置值,如果没有问题,就可以直接进行编译。至于patch文件的下载,同样是在Kernel的相同目录下,寻找文件吗是patch开头的就是了。

内核源代码的解压缩、安装、观察

不论是从CentOS官网下载的SRPM还是从Linux Kernel官网下载的tarball内核源代码,最终都会有一个tarball的内核源代码。

Linux内核编译与管理_第2张图片
Linux Kernel Archive

内核源代码的解压缩与放置目录

#### Kernel:linux-3.10.107.tar.xz

cd /usr/src/kernels/

wget https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.10.107.tar.xz

tar -Jxvf linux-3.10.107.tar.xz -C /usr/src/kernels/

内核源代码下的此目录

Linux内核编译与管理_第3张图片

arch:与硬件平台有关的选项,大部分指的是CPU的类别,例如 x86,x86_64,Xen虚拟支持等;

block:与区块设备较相关的设置数据,区块数据通常指的是大量存储媒体,还包括ext3等文件系统的支持是否允许等;

crypto:内核所支持的加密技术,如 md5或des等;

Documention:与内核有关的帮助文档;

drivers:一些硬件的驱动程序,如显卡、网卡、PCI相关硬件;

firmware:一些旧式硬件的微指令(固件)数据;

fs:内核所支持的filesystems,如vfat、nfs等;

include:一些可让其他程序调用的头(header)定义数据;

init:一些内核初始化的定义功能,包括挂载与init程序的调用等;

ipc:定义Linux操作系统内各程序的通信;

kernel:定义内核的程序、内核状态、线程、程序的调度(schedule)、程序的信号(signal)等;

lib:一些函数库;

mm:与内存单元有关的各种信息,包括swap与虚拟内存等;

net:与网络有关的各项协议信息,还有防火墙(net/ipv4/netfilter/*)等;

security:包括SELinux等安全性设置;

sound:与音效有关的各项模块;

virt:与虚拟化及其有关的信息,目前内核支持的是KVM(Kernel base Virtual Machine)


内核编译的前处理和内核功能选择

内核的目的在管理硬件与提供系统内核功能,因此你必须要先找到系统硬件,并且规划主机的未来任务,这样才能够编译出适合这部主机的内核。所以,真个内核编译的重要工作就是在 “挑选我们想要的功能”。

硬件环境查看与内核功能要求

一部主机硬件环境

CPU:Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz;    #lscpu,/proc/cpuinfo

主板芯片组:Gigabyte B85M-D2V ;    #dmidecode | grep "Base Board Information"

显卡:Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (rev 06),集成显卡;    # lspci | vga

内存:8G;    # /proc/meminfo

硬盘:1TB;    # fidsk -l

网卡:Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 0c);    # lspci | grep Ethernet

至于这台主机的需求,则根据你来定了。

保持干净的源代码:make mrproper

了解了硬件相关的信息后,我们还得要处理一下内核源代码下面的残留文件才行。可以通过一下命令在此目录下处理这些“编译过程的目标文件(*.o)以及设置文件”

make mrproper    

# 这个动作会将以前进行过的内核功能选择文件也删除掉,所以几乎只有第一次执行内核编译前才执行这个动作,其他时候删除前一次编译残留文件,只需要使用如下命令。

make clean

# make clean仅会删除类似目标文件之类的编译过程产生的中间文件,而不会删除设置文件。

开始挑选内核功能:make XXconfig

在 /boot/ 目录下存在一个名为config-xxx的文件,它就是内核的功能列表文件。

/boot/

我们下面要进行的动作,就是制作出该文件。而后续所要进行的编译动作就是通过这个文件来处理的。内核功能的挑选,最后会在 /usr/src/kernel/linux-3.10.107/ 下产生一个 .config 的隐藏文件,这个文件就是 /boot/config-xxxx 的文件。如何建立该文件?

make menuconfig

## 文字模式下可以显示类似图形界面的方式来挑选内核功能选单!

make oldconfig

## 通过使用已经存在的 ./.config 文件内容,使用该文件内的设置值为默认值,只将新版本内核中的新功能选项列出让用户选择,可以简化内核功能的挑选过程!对于作为升级内核源代码后的功能挑选来说,是非常好的一个选项。

make xconfig

## 通过以Qt为图形界面基础功能的图形化界面显示,需要具有X-Window的支持。如KDE就是通过Qt来设计的X-Window。

make gconfig

## 通过以Gtk为图形接口基础功能的图形化界面显示,需要X-Window的支持。如GNOME就是通过Gtk来设计的X-Window。

make config

## 最老式的功能挑选方法,每个选项都以条件式的一条一条的列出让你选择,设置错误的话只能够再次选择,很不人性化。

大致功能选择有上述方法,更多使用说明请参照 README文件。推荐使用 make menuconfig,虽然图形界面的选择很不错,但是是需要图形界面的支持的。如果是升级内核源代码并且需要重新编译,那么使用 make oldconfig 比较合适!

make menuconfig;

## 可能需要 yum install ncurses-devel库,生成 .config文件。

## make mrproper会将 .config 删除的哦!

Linux内核编译与管理_第4张图片
在/usr/src/linux-3.10.107/下
Linux内核编译与管理_第5张图片
3.10.107 Kernel Configuration 选择

若为 [ * ] < * > 则表示编译进内核;

若为 [ M ] 则表示编译成模块;

如果在不知道该选项为何时,且有模块可以选,那么就直接选择为模块。

关于整个内核功能的选择上面,可以这样思考:

“肯定” 内核一定要的功能,直接编译进内核内;

可能在将来会用到的功能,那么尽量编译成为模块;

不知道那个东西要干嘛的,看帮助也看不懂的话,那么就保留默认值,或者是将它编译成模块。

总之,尽量保证内核小而美,剩下的功能就编译成模块,尤其是需要考虑到将来扩展性。

内核功能细项选择

看不懂的选项,务必要使用Help查阅。下面列举几个比较重要的选项。

Linux内核编译与管理_第6张图片
Kernel configuration 细项

General setup

与Linux最相关的程序互动、内核版本说明、是否使用开发中程序代码等信息都在这里设置。这里的选项主要都是针对内核与程序之间的相关性来设计的,基本上,保留默认值就可以了。不要随便取消底下的任何一个项目,因为可能会造成某些程序无法被同时执行。可以依据Help的建议来选择新功能的启动与否。

Linux内核编译与管理_第7张图片
General setup默认值
Linux内核编译与管理_第8张图片
鸟哥的

loadable module + block layer

要让内核能够支援动态的内核模块,那么Enable loadable module support就得设置成开启。block layer则默认是启动的。

Linux内核编译与管理_第9张图片
loadable module默认值
Linux内核编译与管理_第10张图片
鸟哥的


Linux内核编译与管理_第11张图片
block layer默认值
Linux内核编译与管理_第12张图片
鸟哥的

CPU的类型与功能选择

Processor type and feature,挑选你主机的实际CPU形式。KVM和Xen虚拟化服务。

Linux内核编译与管理_第13张图片
Processor type and features 默认值
Linux内核编译与管理_第14张图片
鸟哥的

电源管理功能

Power management and ACPI(Advanced Configuration and Power Interface) options 系统的电源管理机制。但电源管理机制还需要搭配主板和CPU的相关省电功能,才能够实际达到省电的效率啦!

Linux内核编译与管理_第15张图片
Power 默认设置
Linux内核编译与管理_第16张图片
鸟哥的

一些总线(bus)的选项

Bus options(PCI etc.)选项与总线有关!最为常见的 PCI 与 PCI-Express的支持。里面的 PCI-E一定要选,不然可能无法识别到某些PCI-E设备。

Linux内核编译与管理_第17张图片
Bus options 默认值
Linux内核编译与管理_第18张图片
鸟哥的

编译成可执行文件的格式

Executable file formats / Emulations 是给Linux内核运行可执行文件之用的数据,通常是与编译行为有关。 

Linux内核编译与管理_第19张图片
Executable file 默认值
Linux内核编译与管理_第20张图片
鸟哥的

内核的网络功能

Networking support选项相当重要,它包含了防火墙相关的项目!由于防火墙是在启动网络之后再设置即可,所以绝大部分的内容都可以被编译成模块,而且也建议编译成模块。有用到的时候再载入内核即可。

Linux内核编译与管理_第21张图片
Networking support 默认值
Linux内核编译与管理_第22张图片
鸟哥的

各项设备的驱动程序

Device Driver是所有硬件设备的驱动程序库!这里面的选项与主机的硬件有绝对的关系。

这里面的选项很重要,内核发布时的默认值比较符合一般状态的。你可以根据你的主板和相关硬件来进行编译,不过要记得还有“扩展性”的考虑。

Linux内核编译与管理_第23张图片
Device Drivers 默认值
Linux内核编译与管理_第24张图片
鸟哥的
Linux内核编译与管理_第25张图片
鸟哥的

Firmware(固件) Drivers

基本上保留默认设置值就可以了。

文件系统的支持

File system,如果不支持某个文件系统,那么Linux Kernel就无法识别,当然也就无法使用!如Quota,NTFS等文件系统。

这部分很麻烦,因为涉及内核是否能够支持某些文件系统,以及操作系统支持的 partition table项目。在进行选择时,务必要小心!尤其使我们常常用到的网络操作系统(NFS/Samba等),都要选择,否则是无法被识别的。

Linux内核编译与管理_第26张图片
File system 默认值
Linux内核编译与管理_第27张图片
Linux内核编译与管理_第28张图片
鸟哥的

内核骇客、信息安全、密码应用

Kernel hacking 与内核开发者比较相关的部分,这部分建议保留默认之即可;

Security options 属于信息安全方面的设置,包括SELinux这个具体权限强化模块也在这里编入内核。这部分只要记得SELinux作为默认值,且要将 NSA SELinux编进内核即可,其他保留默认值;

Cryptographic API 是密码应用程序接口工具选项,以前的默认加密机制为MD5,近些年则该用了 SHA 机制,只要保留默认值就好了。

Linux内核编译与管理_第29张图片
Kernel hacking默认值
Linux内核编译与管理_第30张图片
Security options默认值
Linux内核编译与管理_第31张图片
Cryptographic API默认值

虚拟化与函数库

Virtualization,我们可以通过虚拟化技术在一部主机上同时启动多个操作系统来运行,Linux内核已经主动的纳入了虚拟化功能。而Linux认可的虚拟化使用的机制为 KVM(Kernel base Virtual Machine)。至于常用的内核函数库也可以全部编译为模块。

Linux内核编译与管理_第32张图片
Virtualization 默认值
Linux内核编译与管理_第33张图片
鸟哥的

Library routines 保留默认的设置值就可以。

Linux内核编译与管理_第34张图片
Library routines 默认值

在这些都设置完毕后,点击 Save ,在出现的窗口中确认文件名为 .config,按下 OK,这样刚刚的设置便被记录下来了。接下来就可以准备进行编译的行为啰!原来的 .config 文件会被更名为 .config.old。

Linux内核编译与管理_第35张图片

无论如何,请记得随时查看 Help那个选项来看一看内容,反正Kernel重新编译的几率不大!花一点时间重新编译一次,然后将该编译完成的参数文件储存下来,未来可以直接将该文件拿来读取!所以花一点时间安装一次就好,这是相当值得的。


内核的编译与安装

将最复杂的内核功能选择完毕后,接下来就是进行这些内核、内核模块的编译了。编译完成后,就需要使用新内核。如何使用新内核呢?就得要考虑 grub 了。

编译内核与内核模块

可以使用 “ make help” 查询所有可用的编译参数。

Linux内核编译与管理_第36张图片
make help
Linux内核编译与管理_第37张图片
make help
Linux内核编译与管理_第38张图片
make help

make vmlinux    #未经压缩的内核

make modules    #仅内核模块

make bzImage    #经压缩过的内核(默认),大写的 i

make all    #进行上述三个动作,Build all targets marked with [*] 

我们常见的 /boot/ 下的内核文件,都是压缩过的内核文件。因此,上诉动作中比较常用的是 modules 和 bzImage 这两个。bzImage可以制作出压缩过的内核,也就是一般我们拿来进行系统开机的信息。

Linux内核编译与管理_第39张图片
/boot/

基本上我们会进行的动作是:

make -j 4 clean    #先清除临时文件

make -j 4 bzImage    #先编译内核

make -j 4 modules    #再编译模块

## make -j 4 clean bzImage modules    #连续动作

## -j [N], --jobs[=N]       同时允许 N 个任务;无参数表明允许无限个任务

## 为啥是 -j 4,因为我的主机有四个CPU核心,这几个核心可以同时进行编译行为,这样在编译时会比较快。如果CPU核心数有多个,那这里就写成可用CPU数量。

编译动作花费的时间依据你选择的选项以及主机硬件的性能而不相同!

最后制作出来的资料是被放置在 /usr/src/kernels/linux-3.10.107/ 目录下,还没有被放到系统的相关路径中哦!

在上面的编译过程中,如果有发生任何错误的话,很可能是由于内核项目的选择不够好,可能就需要重新 make menuconfig 再次检查一下你的相关设置。如果还是无法成功的话,那么或许要将原本的内核数据内的 .config 文件复制到内核源文件目录下,然后加以修改,应该就可以顺利编译出内核。

最后,执行完 make bzImage 命令后,最终结果应该会像这样:

Linux内核编译与管理_第40张图片
make bzImage

并且可以发现你的内核已经编译好而且放置于 /usr/src/kernels/linux-3.10.107/arch/x86/boot/bzImage 里面,这就是我们的内核文件。最重要的就是它,我们等一下就会安装这个文件!然后就是编译模块的部分。make modules 进行完毕后,就等着安装了。

内核的编译(make bzImage)和模块的编译(make modules)

实际安装模块

安装模块前有个地方要特别强调。我们知道模块是放置到 /lib/modules/$(uname -r)/ 目录下,那如果同一个版本(如3.10.107)的模块被反复编译安装,会不会产生冲突呢?新版内核第一次编译不会有这个问题!

重新编译一次,那么这两个版本一模一样时,模块放置的目录也一样,此时就会产生冲突了!有两个解决方法:

方法1:先将旧的模块目录更名,然后才安装内核模块到目标目录中去;

方法2:在 make menuconfig 时,将General setup内的Local version修改成新的名称;

建议使用方法2,这样,模块放置的目录名称就不会相同,这样也就能略过上述的目录同名问题。

使用 make 命令安装模块到正确的目标目录:

make modules_install

Linux内核编译与管理_第41张图片
刚刚安装的内核模块

最终会在 /lib/modules/ 下建立起你这个内核的相关模块哦!接下来就是要准备内核的安装了。这个又与 grub2 有关。

开始安装新内核与多重内核菜单(grub)

现在我们知道内核文件放置于 /usr/src/kernels/linux-3.10.107/arch/x86/boot/bzImage,但是其实系统内核理论上都是在 /boot/ 下,并且为 vmlinuz 开头的文件名。此外,我们也知道一部主机是可以做成多重开机系统的!

所以,我们可以同时保留旧版的内核,并且新增新版的内核在我们的主机上面。

此外,与 grub1 不一样,grub2 建议我们不要直接修改配置文件,而是通过让系统自动检测来处理grub.cfg 这个配置文件的内容。所以,在处理内核文件时,可能就得要知道内核文件的命名规则比较好!

Linux内核编译与管理_第42张图片
grub2.cfg

移动内核到 /boot 且保留旧内核文件

保留旧内核最大的好处就是可以确保系统能够顺利开机。新内核编译成功不代表就完全适用于目前的主机,可能有某些选项忘记选择了,可能导致新内核无法顺利驱动整个主机系统,更糟糕的是可能主机无法成功开机。

内核文件通常以 vmlinuz 为开头,后面跟上内核版本的文件格式。

复制新内核文件到 /boot/ 下并改名 vmlinuz-3.10.107,保留旧内核文件

cp  /usr/src/kernels/linux-3.10.107/arch/x86/boot/bzImage  /boot/vmlinuz-3.10.107


备份 .config 设置文件并改名 config-3.10.107

cp  /usr/src/kernels/linux-3.10.107/.config  /boot/config-3.10.107


给新内核文件添加 X 权限

chmod  a+x  /boot/vmlinuz-3.10.107


备份其他文件

cp  /usr/src/kernels/linux-3.10.107/System.map  /boot/System.map-3.10.107

gzip -c  /usr/src/kernels/linux-3.10.107/Module.symvers  > /boot/symvers-3.10.107



建立相对应的 Initial Ram Disk(initrd)

由于SATA磁盘支持的功能并没有直接编译到内核去,所以要使用 initramfs 来加载才行!

使用如下方法来建立 initramfs,记得要搭配正确的内核版本!

dracut  -v  /boot/initramfs-3.10.107.img  3.10.107

## mkinitrd  -v  /boot/initramfs-3.10.107.img  3.10.107

## Usage: /sbin/dracut  [ option ] ... [ [] ]

## -v  Increase verbosity level



编辑开机选项(grub)

前面的文件大致上都摆放妥当之后,同时得根据你的内核版本来处理文件名。

使用 grub2-mkconfig 来处理你的 grub2 开机选项设置即可!

grub2-mkconfig  -o  /boot/grub2/grub.cfg

## -o, --output=文件      output generated config to FILE [default=stdout]

Linux内核编译与管理_第43张图片
grub2-mkconfig

默认较新版本的内核会放在最前面成为默认的的开机选项,第一个被发现的内核要为你刚刚编译好的内核文件才对!



重新以新内核开机、测试、修改

上述动作都成功后,接下来就是重新开机并选择新内核来启动系统啦!

Linux内核编译与管理_第44张图片

uname -a     #检测内核



额外(单一)内核模块的编译

我们现在知道内核所支持的功能当中,有直接编译到内核内部的,有使用外挂模块的。外挂模块可以想象成就是驱动程序。内核模块依据不同的版本,被分别放置到 /lib/modules/$(uname -r)/kernel/ 下,硬件的驱动则是放置于 /lib/modules/$(uname -r)/kernel/drivers/ 下。

如果我想要忘记编译某个驱动程序,或者是想要使用新的驱动程序,那该怎么办?

编译前注意事项

如果想要自行使用硬件开发商提供的模块来进行编译时,就需要使用到内核所提供的源文件当中的,所谓的 头文件(header include file)来取得驱动模块所需的一些函数库或头的定义。

也就是说,如果想要自行编译内核模块时,就得要拥有内核源代码。

内核源代码放置于 /usr/src/ 下。在2.6版本后,内核使用有趣的方法来设计它的源码放置目录。那就是以 /lib/modules/$(uname -r)/bulid 以及 /lib/modules/$(uname -r)/source 这两个连接文件来指向正确的内核源码防止目录。

Linux内核编译与管理_第45张图片

由于内核模块的编译其实与内核原本的源码有点关系,因此如果你需要重新编译模块时,除了 make,gcc 等主要编译工具外,还需要 kerner-devel 这个软件。

单一模块编译

假设两种情况:

1,如果我的默认内核忘记加入某个功能,而且该功能可以编译成为模块,不过,默认内核却没有将该项功能编译成模块,使得我们没法使用,这怎么办;

2,如果Linux的内核源码并没有某个硬件的驱动程序(module),但硬件厂商提供给Linux使用的驱动程序源码,那我又该如何将该项功能编进内核模块呢?

反正他们都需要内核提供的include表头文件与函数库。

硬件开发商提供的额外模块

如果硬件厂商有提供驱动程序的话,直接下载源码,重新编译,将它放置到内核模块该放置的地方后就能够使用了!

看一下鸟哥的一个例子:

Linux内核编译与管理_第46张图片

需要提醒一点,当自行编译模块时,若内核有更新(如利用自动更新的线上机制)时,则必须要重新编译该模块一次,重复上面的步骤才行!因为这个模块仅针对目前的内核来编译。

利用旧的内核源码进行编译

重新编译模块的话,先要进入源码目录, 执行 make menuconfig,然后将 NTFS(栗子)的选项设定为模块(M),之后执行:

make fs/ntfs/

那么NTFS的模块(ntfs.ko)就会自动被编译出来了,然后将该模块复制到 /lib/modules/3.10.107/kernel/fs/ntfs/ 目录下,在执行 depmod -a 就行了!

内核模块的管理

内核和内核模块是分不开的,至于驱动程序模块在编译的时候,更与内核的源码分不开。因此,必须先了解到: 内核、内核模块、驱动程序模块、内核源码与头文件的相关性,然后才有办法了解到为何编译驱动程序的时候老是需要找到内核的源码才能够顺利编译!然后才会知道,为何内核更新之后,自己之前所编译的模块会失效。

此外,与内核模块有关的,还有那个常被使用的 modprobe 命令,以及开机的时候会读取到的模块定义文件 /etc/modprobe.conf 。 这些资料也必须要了解才行。


重点回顾

内核就是系统上面的一个文件而已,这个文件包含了驱动主机各项硬件的检测程序与驱动模块;

内核模块放置于 /lib/modules/$(uname -r)/kernel/;

驱动程序开发是属于硬件厂商的问题;

由于系统已经将内核编译的相当适合一般使用者,因此一般使用者基本不需要关系编译内核;

编译内核的一般目的:新功能的需求、原内核太过于臃肿,与硬件搭配的稳定性以及其他需求;

编译内核前,最好先了解主机硬件和主机用途,这样才便于选择内核功能;

编译前若想保持内核源码的干净,可使用 make mrproper 来清除临时文件等;

选择内核功能与模块可用make配合:menuconfig、odlconfig、xconfig、gconfig等;

内核功能选择完毕后,一般编译过程为: make bzImage,make modules;

模块编译成功后安装:make modules_install;

内核的安装过程中,需要移动 bzImage文件,建立 initramfs 文件,重建 grub.cfg等;

我们可以自行有硬件开发商官网下载驱动来自星编译内核模块;


内核编译的步骤:

1,下载内核源码;

2,解压到 /usr/src/kernels/ 下;

3,make mrproper ;

4,make menuconfig 挑选功能;

5,make clean 清除过去的临时文件;

6,make bzImage、make modules 编译内核和模块;

7,make modules_install 安装内核模块;

8,复制内核文件到 /boot/ 下;

9,建立 initramfs 文件;

10,grub2-mkconfig 修改/boot/grub2/grub.cfg 文件;


移除自行编译的内核:

rm -rf /lib/modules/3.10.107

rm /boot/vmlinuz-3.10.107  /boot/initramfs-3.10.107.img

grub2-mkconfig -o /boot/grub2/grub.cfg


下面这种方法无法删除自行编译的内核,可以删除升级后多余的内核:

uname -r    #查看内核版本

rpm -qa | grep kernel

yum remove kernel-3.x.xx

你可能感兴趣的:(Linux内核编译与管理)