linux发行版大都提供在线升级机制,大多数情况下不需要自行编译内核!
有一些特殊情况需要自行编译内核,比如嵌入式系统移植.

什么是内核(Kernel)

回到顶部

Linux内核(kernel)作为整个操作系统的最底层,负责硬件的驱动,提供各种内核系统功能,包括防火墙机制、LVM支持、Quota文件系统等.
计算机真正工作的是硬件, 例如数值运算用到CPU、数据储存要用硬盘、图形显示用到显示适配器、声音要有音效芯片、 连接Internet需要网络卡等。内核控制着主机的所有硬件并提供系统所有的功能.硬件的驱动控制是内核工作的一部分! 如果内核不提供某硬件的驱动程序,那么该硬件也就无法被驱动使用.
内核也是一个文件, 这个文件包含了驱动主机各项硬件的检测程序与驱动模块。
内核文件由MBR内的bootloader加载运行,系统读完BIOS后加载MBR内的开机管理程序,开机管理程序加载内核到内存。
然后内核开始检测硬件,挂载根目录并获取内核模块来驱动所有的硬件,之后调用systemd启动系统所需要的服务!
内核文件通常为/boot/vmlinuz-xxx ,可以有多个内核文件,开机的时候只能选择加载一个。

内核也是一个文件,通过源码(source code)编译而成! 内核是直接被读入到主存储器当中的,需要将他编译成为系统可以识别的格式才行! 硬件的驱动程序可以编译成为内核模块,可以在不改变内核的前提下驱动新硬件。 驱动程序的开发是硬件开发商的工作, 提供消费者能够使用的驱动程序是硬件开发商的义务! 所以,如果想要让某个硬件能够在Linux上面运行,可以要求硬件开发商开发Linux上面的驱动程序!这样也可以促进Linux的发展!

更新内核的目的

回到顶部

几乎每一个distribution都已经默认编译好了大量的模块了, 普通用户确实不太需要重新编译内核! 除了BIOS(或UEFI)之外,内核是操作系统中最早被加载到内存的,内核包含了所有可以让硬件与软件工作的信息. 是不是需要将所有内核支持的功能都要编译进内核呢? 那就可以支持目前所有的硬件与可执行的工作啦!! 不是必要的功能,就不要加到内核中,这样才能让Linux跑得更稳、更顺畅!
这也是为什么我们要编译内核的最主要原因了!
内核编译可能有以下几个目的:
添加新功能:
只有最新的内核里才有的功能,为了获得这个功能,只好重新编译内核了。
例如iptables防火墙机制只有在2.4.xx以后的版本里面才有,而新开发的主板芯片组, 很多也需要新的内核推出之后,才能正常且有效率的工作!
去掉不必要的内核功能:
对系统稳定性要求很高的人,可能不太喜欢内核编译了很多莫名其妙的功能,那么就可以重新编译内核来取消一些不必要的功能;
与硬件搭配的稳定性:
Linux内核大多是针对Intel CPU开发的,如果CPU是AMD的,系统有可能运行地不太稳定。 内核也可能没有正确的驱动新的硬件,此时就得重新编译内核来让系统获取正确的模块才好。
其他需求(如嵌入式系统):
需要特殊的环境时,就得自行设计内核了!,有些商业的软件包系统,需要小而美简洁有力的操作系统内核.
重新编译内核虽然可以对硬件进行优化,不过这些优化的步骤对于整体性能的影响是很小的, 如果是为了增加性能而编译内核,基本上效益不大!如果是为了系统稳定性, 那么就很有必要重新编译内核了! 重新编译内核的最主要目的是让系统变的更稳定! 内核的主要工作是在控制硬件!所以编译内核之前, 请先了解一下你的硬件设备,与你这部主机的未来功能! 内核是越简单越好!所以只要将这部主机的未来功能给他编进去就好了!

内核源码的获取方式

回到顶部

CentOS 7使用的3.10.x 版本为长期维护版本,理论上我们也可以升级到后续的主线版本上!不会像以前2.6.x只能升级到2.6.x的后续版本, 而不能改成其他主线版本。不过这也只是理论上而已,因为目前许多的软件依旧与内核版本有关, 例如虚拟化软件qemu,与内核版本之间是有搭配性的关系的,所以,除非你要一口气连同内核相依的软件通通升级,否则最好使用长期维护版本的最新版来处理较佳。 举例来说,CentOS 7 使用的是 3.10.0 这个长期版本,而目前 (2015/09) 这个 3.10 长期版本,最新 的版本为 3.10.89,意思是说, 你最好是拿 3.10.89 来作为内核升级的依据,而不是拿最新的 4.2.1 来升级的意思。 虽然理论上还是拿自家长期维护版本的最新版本来处理比较好,不过initroot因为需要研究虚拟化的 PCI passthrough 技术, 确实也曾经在 CentOS 7.1 的系统中将 3.10.x 的版本升级到 4.2.3 这个版本上! 这样才完成了 VGA 的 PCI passthrough 功能! 所以说,如果你真的想要使用较新的版本来升级, 也不是不可以,只是后果会发生什么问题,就得要自行负责!

既然内核是个文件,要制作这个文件给系统使用则需要编译,既然要有编译,当然就得要有源码啊! 那么源码怎么来?基本上,依据你的 distributions 去挑选的内核源码来源主要有: 原本 distribution 提供的内核源码文件 事实上,各主要 distributions 在推出他们的产品时,其实已经都附上了内核源码了! 不过因为目前资料量太庞大,因此 SRPM 默认已经不给映像站下载了!主要的源码都放置于底下的网站上: 全部的 CentOS 原始 SRPM:http://vault.centos.org/ CentOS 7.1 的 SRPM:http://vault.centos.org/7.1.1503/ CentOS 7.x 开始的版本中,其版本后面会接上发布的日期,因为 CentOS 7.1 是 2015/03 发布的, 因此它的下载点就会是在 7.1.1503 啰!1503 指的就是 2015/03 的意思~ 你可以进入上述的网站后, 到 updates 目录下,一层一层的往下找,就可以找到 kernel 相关的 SRPM 啰! 你或许会说:既然要重新编译,那么干嘛还要使用原本 distributions 发布的源码啊?真没创意~ 话 不是这么说,因为原本的 distribution 发布的源码当中,含有他们设置好的默认设置值, 所以, 我们可以轻易的就了解到当初他们是如何选择与内核及模块有关的各项设置项目的参数值, 那么就 可以利用这些可以配合我们 Linux 系统的默认参数来加以修改,如此一来, 我们就可以修改内核, 调整到自己喜欢的样子啰!而且编译的难度也会比较低一点! 获取最新的稳定版内核源码虽然使用 distribution 发布的内核 source code 来重新编译比较方便,但是,如此一来, 新硬件所需 要的新驱动程序,也就无法藉由原本的内核源码来编译啊! 所以啰,如果是站在要更新驱动程序 的立场来看,当然使用最新的内核可能会比较好啊! Linux 的内核目前是由其发明者 Linus Torvalds 所属团队在负责维护的,而其网站在底下的站址上, 在该网站上可以找到最新的 kernel 信息! 内核官网:http://www.kernel.org/ 交大资科:ftp://linux.cis.nctu.edu.tw/kernel/linux/kernel/ 国高中心:ftp://ftp.twaren.net/pub/Unix/Kernel/linux/kernel/

保留原本设置:利用 patch 升级内核源码 (1)如果你曾经自行编译过内核,那么你的系统当中应该已经存在前几个版本的内核源码, 以及上次你自行编译的参数设置值才对; (2)如果你只是想要在原本的内核底下加入某些特殊功能, 而该功能已经针对内核源码推出 patch 补丁文件时。 那你该如何进行内核源码的更新,以便后续的编译呢? 其实每一次内核发布时,除了发布完整的内核压缩文件之外,也会发布该版本与前一版本的差异性 patch 文件, 关于 patch 的制作我们已经在第二十一章当中提及, 你可以自行前往参考。这里仅 是要提供给你的信息是,每个内核的 patch 仅有针对前一版的内核来分析而已, 所以,万一你想要 由 3.10.85 升级到 3.10.89 的话,那么你就得要下载 patch-3.10.86, patch-3.10.87, patch-3.10.88, patch-3.10.89 等文件,然后依序一个一个的去进行 patch 的动作后, 才能够升级到 3.10.89 喔! 这个重要!不要忘记了。 同样的,如果是某个硬件或某些非官方认定的内核添加功能网站所推出的 patch 文件时,你也必须 要了解该 patch 文件所适用的内核版本,然后才能够进行 patch ,否则容易出现重大错误喔!这个 项目对于某些商业公司的工程师来说是很重要的。 举例来说,initroot的一个高中同学在业界服务,他 主要是进行类似 Eee PC 开发的计划,然而该计划的硬件是该公司自行推出的! 因此,该公司必须 要自行搭配内核版本来设计他们自己的驱动程序,而该驱动程序并非 GPL 授权,因此他们就得要自 行将驱动程序整合进内核!如果改天他们要将这个驱动程序发布,那么就得要利用 patch 的方式, 将 硬件驱动程序文件发布,我们就得要自行以 patch 来更新内核啦! 在进行完 patch 之后,你可以直接检查一下原本的设置值,如果没有问题, 就可以直接编译,而不 需要再重新的选择内核的参数值,这也是一个省时间的方法啊! 至于 patch file 的下载,同样是在 kernel 的相同目录下,寻找文件名是 patch 开头的就是了。

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

回到顶部

不论是从CentOS官网获取的SRPM还是从Linux kernel官网获取的tarball内核源码, 最终都会是tarball的内核源码! 我们从linux kernel官网获取linux-3.10.89.tar.xz这个内核源码文件: ftp://ftp.twaren.net/pub/Unix/Kernel/linux/kernel/v3.x/linux-3.10.89.tar.xz 内核源码的解压缩与放置目录 我们将文件下载到/root目录下。由于内核源码一般建议放置于/usr/src/kernels/目录下,我们可以将它加压缩到这个目录:

              [root@study ~]# tar -Jxvf linux-3.10.89.tar.xz -C /usr/src/kernels/
            
此时会在/usr/src/kernels目录下产生一个新的目录linux-3.10.89! 我们后面的内核编译工作就会在这个目录下进行.
解压缩后的内核源码包含如下的子目录:
arch: 与硬件平台相关的项目,大部分指的是CPU的类别,例如x86, x86_64, Xen虚拟支持等;
block: 与成组设备较相关的设置数据,区块数据通常指的是大量储存媒体!还包括类似 ext3 等文件系 统的支持是否允许等。
crypto: 内核所支持的加密的技术,例如 md5 或者是 des 等等;
Documentation: 与内核有关的一堆说明文件,若对内核有极大的兴趣,要瞧瞧这里!
drivers: 一些硬件的驱动程序,例如显示适配器、网络卡、PCI 相关硬件等等;
firmware: 一些旧式硬件的微脚本 (韧体) 数据;
fs: 内核所支持的 filesystems ,例如 vfat, reiserfs, nfs 等等;
include: 一些可让其他过程调用的标头 (header) 定义数据;
init: 一些内核初始化的定义功能,包括挂载与 init 程序的调用等;
ipc: 定义 Linux 操作系统内各程序的沟通;
kernel: 定义内核的程序、内核状态、线程、程序的排程 (schedule)、程序的讯号 (signle) 等
lib: 一些函数库;
mm: 与内存单元有关的各项数据,包括 swap 与虚拟内存等;
net: 与网络有关的各项协议数据,还有防火墙模块 (net/ipv4/netfilter/*) 等等;
security: 包括 selinux 等在内的安全性设置;
sound: 与音效有关的各项模块;
virt: 与虚拟化机器有关的信息,目前内核支持的是 KVM (Kernel base Virtual Machine)
建议多看看Documentation目录下的文件!

内核编译的预处理

回到顶部

内核管理硬件并提供系统内核功能,必须要先找到系统硬件, 规划好主机的未来任务,这样才能够编译出适合这部主机的内核! 整个内核编译的重要工作就是挑选需要的功能。 下面就以一部主机软/硬件环境为例来说明,解释如何编译内核!
initroot的一部主机硬件环境如下 (在虚拟机中,通过 /proc/cpuinfo 及 lspci 观察):

CPU:Intel(R) Xeon(R) CPU E5-2650 主板芯片组: KVM 虚拟化模拟的主版 (Intel 440FX 兼容) 显示适配器: Red Hat, Inc. QXL paravirtual graphic card 内存: 2.0GB 内存 硬盘: KVM Virtio 界面磁盘 40G (非 IDE/SATA/SAS 喔!) 网络卡: Red Hat, Inc Virtio network device
这部主机希望可以通过虚拟化功能来处理学生的练习用虚拟机,这部主机也是用来放置学校上课教材的机器, 因此,这部主机的 I/O 需求须要好一点,未来还需要开启防火墙、WWW服务、FTP服务等,基本上,用途就是一部小型的服务器。

保持源码干净: make mrproper

在编译内核之前,需要先清理一下内核源码中的残留文件,这些文件是上一次编译过程中生成的目标文件(*.o)以及相关的配置文件:
              [root@study ~]# cd /usr/src/kernels/linux-3.10.89/
              [root@study linux-3.10.89]# make mrproper
            
make mrproper会将以前配置好的内核功能选择文件也删除掉, 所以几乎只有第一次执行内核编译前才进行这个动作, 只删除前一次编译生成的残留数据:
            [root@study linux-3.10.89]# make clean
            
make clean仅删除类似目标文件之类的编译过程产生的中间文件,而不会删除配置文件! 我们是第一次进行编译,因此请执行make mrproper!

24.2.3 配置内核功能: make XXconfig

/boot/目录下存在一个名为config-xxx的文件,这个文件其实就是内核功能列表文件! 内核的编译就是通过这个文件来处理的!
执行内核功能配置命令,就会在/usr/src/kernels/linux-3.10.89/目录下生成一个名为.config的隐藏文件, 这个文件就是/boot/config-xxx!
常见内核功能配置命令:
              make menuconfig
              最常用,文本模式下显示类似图形接口的方式,不需要启动X Window就能够挑选内核功能菜单!

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

              make xconfig
              通过Qt为图形接口基础功能的图形化接口显示,需要具有 X window 的支持。
                例如KDE就是通过Qt来设计的 X Window,因此你如果在 KDE 画面中,可以使用此一项目。

              make gconfig
              通过以 Gtk 为图形接口基础功能的图形化接口显示,需要具有 X window 的支持。
                例如GNOME就是透过Gtk来设计的X Window,因此你如果在GNOME画面中,可以使用此一项目。

              make config
              最旧式的功能挑选方法,每个项目都以条列式一条一条的列出让你选择,如果设置错误只能够再次选择,很不人性化啊!
            
更多的方式可以参考内核目录下的README文件。个人比较偏好make menuconfig! 如果你喜欢使用图形接口,使用鼠标选择所需要的功能,也可以使用make xconfig或make gconfig,不过需要有相关的图形接口支持! 如果你是升级内核源码并且需要重新编译,那么使用make oldconfig会比较合适!
通过既有的设置来处理内核项目与功能的选择 既然CentOS 7已经有提供它的内核设置值,我们也只是想要修改一些小细节而已, 那么可不可以以CentOS 7的内核功能为基础, 然后来细部微调其它的设置呢?当然可以啊!你只要这样做即可:
              [root@study linux-3.10.89]# cp /boot/config-3.10.0-229.11.1.el7.x86_64 .config
            
以 make menuconfig 来说,出现的画面会有点像这样: 注意,你可能会被要求安装好多软件,请自行使用 yum 来安装喔!这里不再介绍了!
另外: 不要再使用make mrproper!因为我们已经复制了.config!使用make mrproper会将.config删除! initroot网站建设服务 make menuconfig内核功能配置示意图
内核配置界面主要分为两大部分,一是大框框内的反白光柱,另一个则是底下的小框框,里面有select, exit 与 help 三个选项。
这几个组件的大致用法如下:
左右箭头键: 可以移动最底下的 <Select>, <Exit>, <Help>项目;
上下箭头键: 可以移动上面大框框部分的反白光柱,若该行有箭头 (--->) 则表示该行内部还有其他子项目需要来设置;
选定项目: 以上下键选择好想要设置的项目之后,并以左右键选择 <Select> 之后, 按下 Enter就可以进入该项去作更进一步的细部设置了;
可挑选之功能: 在细部项目的设置当中,如果前面有 [ ] 或 <> 符号时,该项目才可以选择, 使用空格键来选择;
若为 [*] <*> 则表示编译进内核;若为 <M> 则表示编译成模块! 在不知道该项目为何时,且有模块可以选,那么就可以直接选择为模块!
当在子项目目选择 <Exit> 后,并按下 Enter ,就可以离开该细部项目!
基本上建议只要上下左右的箭头键、空格键、Enter这六个按键就好了!
不要使用 Esc ,否则一不小心就有可能按错的!
关于整个内核功能的选择上面,建议你可以这样思考:
肯定内核一定要的功能,直接编译进内核内;
可能在未来会用到的功能,那么尽量编译成为模块;
不知道那个东西要干嘛的,看 help 也看不懂的话,那么就保留默认值,或者将他编译成为模块;
总之,尽量保持内核小而美,剩下的功能就编译成为模块,尤其是需要考虑到未来扩充性, 像initroot之前认为螃蟹卡就够我用的了, 结果,后来竟然网站流量大增,initroot只好改换 3Com的网络卡。不过,我的内核却没有相关的模块可以使用~因为.....initroot自己编译的内核忘记加入这个模块了。 最后,只好重新编译一次内核的模块,呵呵!真是惨痛的教训啊!

内核配置

回到顶部

内核可以选择的配置项目有很多!光是第一面,就有17个项目,每个配置项目还有不同的子项目! 每个项目都有<Help>说明,看到不懂的项目,可使用Help查阅! 下面我们就来看看如何选择项目! 我们使用CentOS 7.1的内核配置文件来进行默认的设置,基本上许多默认的设置都不用调整。 底下只列出几个比较重要的设置项目。其他更详细的内核功能配置项,还请自行参考help说明!

            General setup
            与Linux最相关的程序互动、内核版本说明、是否使用开发中程序代码等信息都在这里设置的。
            这里的项目主要是针对内核与程序之间的相关性来设计的,基本上,保留默认值即可!
            不要随便取消底下的任何一个项目,因为可能会造成某些程序无法被同时执行!
            不过底下有非常多新的功能,如果你有不清楚的地方,可以按 <Help> 进入查阅,里面会有一些建议!
            你可以依据Help的建议来选择新功能的启动与否!

            (initroot)Local version - append to kernel release
            [*] Automatically append version information to the version string
            希望内核版本成为3.10.89.initroot,这里可以就这样设置
            Kernel compression mode (Bzip2) --->
            建议选择成为Bzip2,压缩性能好!
            .....(其他保留默认值).....
            <M> Kernel .config support
            [ ] Enable access to .config through /proc/config.gz (NEW)
            让.config内核功能列表写入实际的内核文件中!这样就不需要保留.config文件了!
            (20) Kernel log buffer size (16 => 64KB, 17 => 128KB)
            # CentOS 7 增加了内核的登录文件容量!占用了 2 的 20 次方,大概用了 1MB 的容量!
            .....(其他保留默认值).....
            [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
            () Initramfs source file(s)
            # 这是一定要的!因为要支持开机时加载 initail RAM disk 嘛!
            [ ] Optimize for size
            # 减低内核的文件大小,其实 gcc 参数使用 -Os 而不是 -O2。不过我们不是嵌入式系统,不太需要!
            [ ] Configure standard kernel features (expert users) --->
            [ ] Embedded system
            # 上面两个在决定是否支持嵌入式系统呢?我们这里是桌机,所以这个不用选择了!
            .....(其他保留默认值).....

            loadable module + block layer
            要让你的内核能够支持动态的内核模块,那么底下的第一个设置就得要启动才行!
            至于第二个 block layer 则默认是启动的, 你也可以进入该项目的子项目设置,选择其中你认为需要的功能即可!

            [*] Enable loadable module support --->
            <==底下为子项目
            --- Enable loadable module support
            [*] Forced module loading
            [*] Module unloading
            其实initroot认为这个项目可能可以选择的!免得常常无法卸除模块!
            [*] Forced module unloading
            [*] Module versioning support
            [*] Source checksum for all modules
            [*] Module signature verification
            [ ] Require modules to be validly signed
            [*] Automatically sign all modules Which hash algorithm should modules be
              signed with?
            # 可以选择 SHA256即可!

            ================================================================================
            -*- Enable the block layer --->
            <==看吧!默认就是已经选择了!底下为子项目
            -*- Block layer SG support v4
            -*- Block layer SG support v4 helper lib
            [*] Block layer data integrity support
            [*] Block layer bio throttling support Partition Types --->
            # 至少底下的数个项目要选择!
            [*] Macintosh partition map support
            [*] PC BIOS (MSDOS partition tables) support
            [*] Windows Logical Disk Manager (Dynamic Disk) support
            [*] SGI partition support
            [*] EFI GUID Partition support
            .....(其他保留默认值).....

            IO Schedulers --->
            # 磁盘队列的处理方式
            <*> Deadline I/O scheduler
            <*> CFQ I/O scheduler
            [*] CFQ Group Scheduling support
            # initroot非常建议将此项目设置为内核功能!
            
            Default I/O scheduler (Deadline) --->

            CPU 的类型与功能选择
            # 相当建议改为 Deadline进入Processor type and features后,请挑选你主机的实际 CPU 形式。initroot这里使用的是
            Intel E5 的CPU, 而且initroot的主机还有启动 KVM 这个虚拟化的服务 (在一部主机上面同时启动多个操作系统),
            因此,所以底下的选择是这样的:
            .....(其他保留默认值).....
            [*] Linux guest support --->
            [*] Enable paravirtualization code
            # 提供 Linux 虚拟化功能
            # 至少底下这几样一定要有选择才好!
            [*] Paravirtualization layer for spinlocks
            [*] Xen guest support
            [*] KVM Guest support (including kvmclock)
            [*] Paravirtual steal time accounting
            .....(其他保留默认值).....
            Processor family (Generic-x86-64) --->
            # 除非你是旧系统,否则就用他!
            [*] Enable Maximum number of SMP Processors and NUMA Nodes
            [*] Multi-core scheduler support
            Preemption Model (No Forced Preemption (Server) --->
            # 调整成 server 喔!原本是 desktop
            .....(其他保留默认值).....
            Timer frequency (300 HZ) --->
            # server 设置成 300 即可!
            # 这个项目则与内核针对某个事件立即回应的速度有关。Server 用途可以调整到
            # 300Hz 即可,如果是桌面计算机使用,需要调整高一点,例如 1000Hz 较佳!
            .....(其他保留默认值).....

            电源管理功能
            如果选择了Power management and ACPI options之后,就会进入系统的电源管理机制中。 其实电
            源管理机制还需要搭配主板以及 CPU 的相关省电功能,才能够实际达到省电的效率啦! 不论是
            Server 还是 Desktop 的使用,在目前电力不足的情况下,能省电就加以省电吧!
            .....(其他保留默认值).....
            [*] ACPI (Advanced Configuration and Power Interface) Support --->
            # 对嵌入式系统来说,由于可能会增加内核容量故需要考虑考虑。至于 desktop/server 当然就选择啊
            # 至于内容子项目大致保持默认值即可
            CPU Frequency scaling --->
            # 决定 CPU 频率的一个重要项目,基本上的项目是 ondemand 与 performance 两者!
            <M> CPU frequency translation statistics
            [*] CPU frequency translation statistics details
            Default CPUFreq governor (ondemand) --->
            # 现在大家都建议用这个!
            -*- 'performance' governor
            <*> 'powersave' governor
            <*> 'userspace' governor for userspace frequency scaling
            -*- 'ondemand' cpufreq policy governor
            <*> 'conservative' cpufreq governorx86 CPU frequency scaling drivers --->
            # 这个子项目内全部都是省电机制,能编成模块的全部选择!要加入内核的都加入就对了!
            一些总线 (bus) 的选项
            这个Bus options (PCI etc.)项目则与总线有关啦!分为最常见的 PCI 与 PCI-express 的支持,还
            有笔记本电脑常见的 PCMCIA 插卡啊!要记住的是,那个 PCI-E 的界面务必要选取!不然你的新
            显示适配器可能会捉不到!
            [*] PCI support
            [*] Support mmconfig PCI config space access
            [*] PCI Express support
            <*> PCI Express Hotplug driver
            .....(其他在 PCI Express 底下的项目大多保留默认值).....
            -*- Message Signaled Interrupts (MSI and MSI-X)
            <*> PCI Stub driver
            # 如果要玩虚拟化,这个部份建议编进内核!
            .....(其他保留默认值).....

            编译后执行档的格式
            选择Executable file formats / Emulations会见到如下选项。 底下的选项必须要勾选才行喔!
              因为是给 Linux 内核运作执行文件之用的数据。通常是与编译行为有关啦!
            -*- Kernel support for ELF binaries
            [*] Write ELF core dumps with partial segments
            <*> Kernel support for scripts starting with #!
            <M> Kernel support for MISC binaries
            [*] IA32 Emulation
            <M> IA32 a.out support
            [*] x32 ABI for 64-bit mode
            # 因为我们的 CentOS 已经是纯 64 位的环境!所以个人建议这里还是要选择仿真 32 位的功能!
            # 不然若有些比较旧的软件,恐怕会无法被你的系统所执行喔!
            
            内核的网络功能
            这个Networking support项目是相当重要的选项,因为他还包含了防火墙相关的项目!就是未来在
            服务器篇会谈到的防火墙 iptables 这个数据啊!所以,千万注意了!在这个设置项目当中,很多东
            西其实我们在基础篇还没有讲到, 因为大部分的参数都与网络、防火墙有关!由于防火墙是在启动
            网络之后再设置即可,所以绝大部分的内容都可以被编译成为模块,而且也建议你编成模块!有用到
            再载入到内核即可啊!
            --- Networking support
            Networking options --->
            # 就是这个光啊!里面的数据全部都是重要的防火墙项目!尽量编成模块啰!
            # 至于不晓得功能的部分,就尽量保留默认值即可!
            # 底下的数据中,initroot只有列出原本没有选择,后来建议选择的部份
            [*] Network packet filtering framework (Netfilter) --->
            # 这个就是我们一直讲的防火墙部分!里面子项目几乎全选择成为模块!
            --- Network packet filtering framework (Netfilter)
            Core Netfilter Configuration --->
            <M> Transparent proxying support
            ================================================================================
            [*] QoS and/or fair queueing
            Network testing --->
            <==内容同样全为模块! --->
            <==保留成模块默认值
            ================================================================================#
            底下的则是一些特殊的网络设备,例如红外线啊、蓝芽啊! # 如果不清楚的话,就使用模块吧!除非你真的知道不要该项目! 
            <M> Bluetooth subsystem support --->
            # 这个是蓝芽支持,同样的,里面除了必选之外,其他通通挑选成为模块!
            [*] Wireless --->
            # 这个则是无线网络设备,里面保留默认值,但可编成模块的就选模块
            <M> WiMAX Wireless Broadband support --->
            # 新一代的无线网络,也请勾选成为模块!
            <M> NFC subsystem support --->
            # 跟卡片比较有关的芯片支持,建议编译成模块,内部数据也是编译成模块为佳!

            各项装置的驱动程序
            进入Device
            Drivers这个是所有硬件装置的驱动程序库!哇!光是看到里面这么多内容,initroot头都
            昏了~ 不过,为了你自己的主机好,建议你还是得要一个项目一个项目的去挑选挑选才行~ 这里面
            的数据就与你主机的硬件有绝对的关系了!
            在这里面真的很重要,因为很多数据都与你的硬件有关。内核推出时的默认值是比较符合一般状态的,
            所以很多数据其实保留默认值就可以编的很不错了!不过,也因为较符合一般状态, 所以内核额外
            的编译进来很多跟你的主机系统不符合的数据,例如网络卡装置~ 你可以针对你的主板与相关硬件
            来进行编译。不过,还是要记得有未来扩充性的考虑! 之前initroot不是谈过吗,我的网络卡由螃
            蟹卡换成 3Com 时,内核捉不到~ 因为...initroot并没有将 3Com 的网络卡编译成为模块啊!
            @_@
            # 大部分都保留默认值,initroot只是就比较重要的部份拿出来做说明而已!
            <M> Serial ATA and Parallel ATA drivers --->
            # 就是 SATA/IDE 磁盘!大多数选择为模块!
            [*] Multiple devices driver support (RAID and LVM)
            -*- Network device support --->
            # 就是 LVM 与 RAID !要选要选!
            ---> 
            # 网络方面的设备,网卡与相关媒体啦!
            -*- Network core driver support
            <M> Bonding driver support
            <M> Ethernet team driver support
            <M> Virtio network driver --->
            -*- Ethernet driver support --->
            # 与网卡整合有关的项目!要选!  
            # 与 bonding 差不多的功能!要选!
            # 虚拟化的网卡驱动程序!要选!
            # 以太网卡!里面的一堆 10G 卡要选!
            <M> PPP (point-to-point protocol) support
            <M> Chelsio 10Gb Ethernet support
            <M> Intel(R) PRO/10GbE support
            
            
            # 与拨接有关的协议!
            USB Network Adapters --->
            [*] Wireless LAN --->
            # 当然全部编译为模块!
            # 无线网卡也相当重要!里面全部变成模块!
            
            ================================================================================
            [ ] GPIO Support --->
            # 若有需要使用类似树莓派、香蕉派才需要这东西!
            
            <M> Multimedia support Graphics support --->
            # 显示适配器!如果是作为桌上型使用,这里就重要了!
            
            <M> Sound card support --->
            [*] USB support --->
            # 多媒体装置,如影像撷取、广播声卡等等
            
            # 声卡,同样的,桌面计算机使用时,比较重要!
            
            # 就是 USB!底下几个内部的子项目要注意是勾选的!
            
            <*> xHCI HCD (USB 3.0) support --->
            <*> EHCI HCD (USB 2.0) support
            <*> OHCI HCD support
            <*> UHCI HCD (most Intel and VIA) support
            <M> InfiniBand support --->
            # 较高阶的网络设备,速度通常达到 40Gb 以上!
            
            <M> VFIO Non-Privileged userspace driver framework --->
            [*] VFIO PCI support for VGA devices
            # 作为 VGA passthrought 用!
            [*] Virtualization --->
            drivers Virtio drivers --->
            # 虚拟化的驱动程序!
            # 在虚拟机里面很重要的驱动程序项目!
            
            [*] IOMMU Hardware Support --->
            # 同样的与虚拟化相关性较高!
            至于 Firmware Drivers的项目,请视你的需求来选择~基本上就保留设置值即可!所以initroot这里就不显示啰!

            文件系统的支援
            文件系统的支持也是很重要的一项内核功能!因为如果不支持某个文件系统,那么我们的
            Linux kernel 就无法认识,当然也就无法使用啦!例如Quota, NTFS 等等特殊的filesystem 。 
            这部份也是有够麻烦~因为涉及内核是否能够支持某些文件系统,以及某些操作系统支持的partition table 项目。
            在进行选择时,也务必要特别的小心在意喔!
            尤其是我们常常用到的网络操作系统(NFS/Samba 等等),以及基础篇谈到的 Quota 等,你都得要勾选啊!否则是无法被支持的。
            如果你有兴趣,也可以将 NTFS 的文件系统设置为可擦写看看啰!
            #底下仅有列出比较重要及与默认值不同的项目而已喔!所以项目少很多!
            <M> Second extended fs support
            # 默认已经不支持ext2/ext3,这里我们将他加回来!
            <M> Ext3 journalling file system support
            [*] Default to 'data=ordered' in ext3 (NEW)
            [*] Ext3 extended attributes (NEW)
            [*] Ext3 POSIX Access Control Lists
            <M> The Extended 4 (ext4) filesystem
            # 一定要有的支持
            <M> Reiserfs support
            <M> XFS filesystem support
            [*] XFS Quota support
            # 一定要有的支持!
            [*] XFS POSIX ACL support
            [*] XFS Realtime subvolume support
            # 增加这一项好了!
            # 最好有支持!
            <M> Btrfs filesystem support
            [*] Quota support
            <*> Quota format vfsv0 and vfsv1 support
            <*> Kernel automounter version 4 support (also supports v3)
            <M> FUSE (Filesystem in Userspace) support DOS/FAT/NT Filesystems --->
            <M> MSDOS fs support
            <M> VFAT (Windows-95) fs support (950) Default codepage for FAT
            # 要改成这样喔!中文支持!
            (utf8) Default iocharset for FAT
            # 要改成这样喔!中文支持!
            <M> NTFS file system support
            # 建议加上NTFS喔!
            [*] NTFS write support Pseudo filesystems --->
            # 让他可擦写好了!
            
            # 类似 /proc ,保留默认值
            -*- Miscellaneous filesystems
            [*] Network File Systems --->
            <M> NFS client support
            <M> NFS server support
            [*]
            <M>
            # 其他文件系统的支持,保留默认值
            # 网络文件系统!很重要!也要挑挑!
            
            
            [*] NFS server support for NFS version 4
            [*] CIFS support (advanced network filesystem, SMBFS successor) --->

            Extended statistics Provide CIFS
            client caching support
            -*- Native language support --->
            #选择默认的语系
            (utf8) Default NLS Option
            <M> Traditional Chinese charset (Big5)
            内核黑客、信息安全、密码应用
            再接下来有个Kernel hacking的项目,那是与内核开发者比较有关的部分,这部分建议保留默认值即可,
            应该不需要去修改他!除非你想要进行内核方面的研究喔。然后底下有个
            Security Options ,那是属于信息安全方面的设置,
            包括 SELinux 这个细部权限强化模块也在这里编入核心的!这个部份只要记得SELinux作为默认值,且务必要将NSA SELinux
            编进内核即可,其他的细部请保留默认值。
            另外还有Cryptographic API
            这个密码应用程序编程接口工具选项,以前的默认加密机制为MD5,
            近年来则改用了SHA这种机制。
            不过,反正默认已经将所有的加密机制编译进来了,所以也是可
            以保留默认值啦!都不需要额外修改就是了!
            虚拟化与函数库
            虚拟化是近年来非常热门的一个议题,因为计算机的能力太强,所以时常闲置在那边,
            此时,我们可以通过虚拟化技术在一部主机上面同时运行多个操作系统,这就是所谓的虚拟化。
            Linux内核已经主动的纳入虚拟化功能!而Linux认可的虚拟化使用的机制为
            KVM (Kernel base Virtual Machine)。
            至于常用的内核函数库也可以全部编为模块!
            [*] Virtualization --->
            --- Virtualization
            <M> Kernel-based Virtual Machine (KVM) support
            <M> KVM for Intel processors support
            <M> KVM for AMD processors support
            [*] Audit KVM MMU
            [*] KVM legacy PCI device assignment support
            <M>Host kernel accelerator for virtio net
            #虽然已经有VFIO,不过建议还是选起来!
            ================================================================================
            Library routines --->
            #这部份全部保留默认值即可!
            
现在回到设置首页,点击下方的Save选项,在出现的窗口中确认文件名为.config,直接按OK按钮,这样就将刚刚处理完毕的选项保存下来了。 接下来可以选择离开菜单画面,准备让我们来进行编译的行为啰。 要请你注意的是,上面的资料主要是适用在initroot的个人机器上面的, 目前initroot比较习惯使用原本distributions提供的默认内核,因为他们也会主动的进行更新,所以initroot就懒的自己重编内核了~ 此外,因为initroot重视的地方在于网络服务器与虚拟化服务器上面,所以里头的设置少掉了相当多的个人桌上型Linux的硬件编译!
所以,如果你想要编译出一个适合你的机器的内核,那么可能还有相当多的地方需要来修正的!不论如何,请随时以Help那个选项来看一看内容吧!反正 Kernel重编的机率不大!花多一点时间重新编译一次!然后将该编译完成的参数文件储存下来,未来就可以直接将该文件叫出来读入了! 所以花多一点时间安装一次就好!那也是相当值得的!

内核和内核模块的编译

回到顶部

内核功能配置完成后,就可以编译内核和内核模块了. 可以先使用make help查阅可用的编译参数,编译的命令大概有如下这些:

              [root@study linux-3.10.89]# make bzImage
              编译后生成压缩的内核(默认)
              [root@study linux-3.10.89]# make vmlinux
              编译后生成未经压缩的内核
              [root@study linux-3.10.89]# make modules
              仅编译内核模块
              [root@study linux-3.10.89]# make all
              上述三个动作都会执行   
            
/boot/目录下的内核文件都是经过压缩过的内核文件,上述的命令中比较常用的是modules与bzImage这两个, bzImage可以制作出压缩的内核,也就是我们经常用来开机启动的内核.
所以我们实际编译内核经常用到的是下面的步骤:
              [root@study linux-3.10.89]# make -j 4 clean
              先清除中间文件
              [root@study linux-3.10.89]# make -j 4 bzImage
              编译内核
              [root@study linux-3.10.89]# make -j 4 modules
              再编译模块
              [root@study linux-3.10.89]# make -j 4 clean bzImage modules
              连续动作
            
编译的时间根据选择的项目以及主机硬件的性能而不同,基本都会花费相当长的时间。 -j 4表示同时使用4个cpu核进行编译,这样在提高编译速度! 如果编译顺利完成,会显示类似如下的信息:
              Setup is 16752 bytes (padded to 16896 bytes). System is 4404 kB CRC 30310acf Kernel: arch/x86/boot/bzImage is ready (#1)
              [root@study linux-3.10.89]# ll arch/x86/boot/bzImage
              -rw-r--r--. 1 root root 4526464 Oct 20 09:09 arch/x86/boot/bzImage
            
最后编译生成的最终文件被放置在/usr/src/kernels/linux-3.10.89/目录下! 编译过程中如果发生错误, 很可能是由于内核项目的选择有问题,可能需要重新执行make menuconfig,检查相关设置! 如果还是无法成功,可以将原本的内核数据内的.config 文件,复制到你的内核原始文件目录下, 然后据以修改,应该就可以顺利的编译出你的内核了。
可以发现内核已经编译好而且放置在/usr/src/kernels/linux-3.10.89/arch/x86/boot/bzImage,这个就是内核文件! 稍后会安装这个内核文件.然后就是模块编译完毕make modules,就等着安装!

模块安装

回到顶部

模块是放置到/lib/modules/$(uname -r)目录下的,如果同一个版本的模块被反复编译后来安装时,就会覆盖上一个版本的文件. 为了备份老的模块文件,可以先将旧的模块目录更名,然后再安装内核模块到目标目录去;
更合理的做法是每次编译前,在make menuconfig中,重新修改General setup中的Local version。
这样模块放置的目录名称就不会相同,也就不需要每次都备份目录了! 使用make modules_install安装模块到正确的目标目录:

              [root@study linux-3.10.89]# make modules_install
              [root@study linux-3.10.89]# ll /lib/modules/
              drwxr-xr-x. 7 root root 4096 Sep 9 01:14 3.10.0-229.11.1.el7.x86_64 
              drwxr-xr-x. 7 root root 4096 May 4 17:56 3.10.0-229.el7.x86_64 
              drwxr-xr-x. 3 root root 4096 Oct 20 14:29 3.10.89initroot
            
内核模块安装好后会在/lib/modules目录下建立起内核的相关模块!
接下来安装新内核

内核安装

回到顶部

生成的内核文件放置在/usr/src/kernels/linux-3.10.89/arch/x86/boot/bzImage 但grub在加载内核的时候,是在/boot目录下寻找vmlinuz开头的内核文件名。 我们将同时保留旧版的内核,并且新增新版的内核。做成多重引导系统! 移动内核到/boot且保留旧内核文件,这样做的好处是可以确保系统能够顺利开机! 因为新内核还没有经过开机测试,如果新内核有问题,我们还可以选择使用旧的内核开机! grub2建议不要直接修改配置文件,而是通过让系统自动侦测来处理grub.cfg配置文件的内容。 所以,在处理内核文件时,可能就得要知道内核文件的命名规则! 内核文件通常以vmlinuz开头,接上内核版本为依据的文件名格式,

              [root@study linux-3.10.89]# cp arch/x86/boot/bzImage /boot/vmlinuz-3.10.89initroot
              [root@study linux-3.10.89]# cp .config /boot/config-3.10.89initroot 
              建议配置文件也复制备份
              [root@study linux-3.10.89]# chmod a+x /boot/vmlinuz-3.10.89initroot
              [root@study linux-3.10.89]# cp System.map /boot/System.map-3.10.89initroot
              [root@study linux-3.10.89]# gzip -c Module.symvers> /boot/symvers-3.10.89initroot.gz
              [root@study linux-3.10.89]# restorecon -Rv /boot
              建立相对应的 Initial Ram Disk (initrd)
            
由于initroot的系统使用SATA磁盘,加上刚刚SATA磁盘支持的功能并没有直接编译到内核去,需要使用initramfs来加载才行! 使用如下的方法来建立initramfs吧!记得搭配正确的内核版本喔!
            [root@study ~]# dracut -v /boot/initramfs-3.10.89initroot.img 3.10.89initroot
            

编辑开机菜单

回到顶部

接下来我们使用grub2-mkconfig制作grub2开机菜单.

              [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
              Generating grub configuration file
              ......
              Found linux image:
              /boot/vmlinuz-3.10.89initroot
              # 应该要最早出现!
              Found initrd image:
              /boot/initramfs-3.10.89initroot.img
              .......
            
默认较新版本的内核会放在最前面成为默认的开机菜单项目,需要确认第一个被发现的内核为刚刚我们编译好的内核文件才对! 否则可能会使用旧内核开机。

新内核开机、测试、修改

回到顶部

接下来重新启动并选择新内核启动系统!系统顺利启动之后,使用 uname -a 会出现类似底下的数据:

              [root@study ~]# uname -a
              Linux www.initroot.com 4.15.0-191-generic #202-Ubuntu SMP Thu Aug 4 01:49:29 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
            
包括内核版本与支持的硬件平台都是符合预期的,说明所编译的内核就是成功的! 如果运行一阵子后,系统还是稳定的情况下,那就能够将default值使用这个新的内核来作为默认开机啰! 这就是内核编译了

单独编译内核模块

回到顶部

内核所支持的功能,有直接编译到内核的,也有编译为模块的,这些内核模块依据不同的版本,被分别放置到 /lib/modules/$(uname -r)/kernel/目录中,硬件的驱动程序则是放置到 /lib/modules/$(uname -r)/kernel/drivers/当中!
如果刚刚有些驱动程序忘记编译成为模块了,那是否需要重新进行上述的所有动作? 又如果我想要使用硬件厂商发布的新驱动程序,那该如何是好? 内核提供一些内核工具供硬件开发商使用,硬件开发商针对内核提供的功能来设计驱动程序模块,因此, 我们如果想要自行使用硬件开发商所提供的模块来进行编译时,就需要使用到内核所提供的原始档当中, 所谓的头文件案(header include file) 来取得驱动模块所需要的一些函数库或标头的定义! 也因此我们常常会发现到,如果想要自行编译核心模块时,就得要拥有内核源码! 内核源码可能放置在/usr/src/目录下,早期的内核源码被要求一定要放置到/usr/src/linux/目录下, 不过,如果你有多个内核在一个Linux系统当中,而且使用的源码并不相同时,呵呵~问题可就大了!所以,在 2.6版以后,内核使用比较有趣的方法来设计他的源码放 置目录,那就是以/lib/modules/$(uname -r)/build 及/lib/modules/$(uname -r)/source 这两个链接文件来指向正确的内核源码放置目录。如果以我们刚刚由kernel 3.10.89initroot建立的内核模块来说, 那么他的内核模块目录下有什么咚咚?

              [root@study ~]# ll -h /lib/modules/3.10.89initroot/
              lrwxrwxrwx.  1 root root 30 Oct 20 14:27 build -> /usr/src/kernels/linux-3.10.89
              drwxr-xr-x. 11 root root 4.0K Oct 20 14:29 kernel 
              -rw-r--r--.  1 root root 668K Oct 20 14:29 modules.alias
              -rw-r--r--.  1 root root 649K Oct 20 14:29 modules.alias.bin
              -rw-r--r--.  1 root root 5.8K Oct 20 14:27 modules.builtin
              -rw-r--r--.  1 root root 7.5K Oct 20 14:29 modules.builtin.bin
              -rw-r--r--.  1 root root 208K Oct 20 14:29 modules.dep
              -rw-r--r--.  1 root root 301K Oct 20 14:29 modules.dep.bin
              -rw-r--r--.  1 root root 316 Oct 20 14:29 modules.devname
              -rw-r--r--.  1 root root 81K Oct 20 14:27 modules.order
              -rw-r--r--.  1 root root 131 Oct 20 14:29 modules.softdep
              -rw-r--r--.  1 root root 269K Oct 20 14:29 modules.symbols
              -rw-r--r--.  1 root root 339K Oct 20 14:29 modules.symbols.bin
              lrwxrwxrwx.  1 root root 30 Oct 20 14:27 source -> /usr/src/kernels/linux-3.10.89
            
modules.dep文件记录了内核模块的相依属性的地方,依据该文件,可以简单的使用modprobe命令来加载模块! 至于内核源码提供的头文件,则放置到/usr/src/kernels/linux-3.10.89/include/目录中,当然就是藉由build和source这两个链接文件来获取所在目录! 内核模块的编译与内核源码有点关系,如果你需要重新编译模块,除了make,gcc等主要的编译工具外,还需要的就是kernel-devel这个软件! 而如果你想要在默认的内核底下新增模块的话,那么就得找到kernel的SRPM文件了!安装该文件并获取source code后,才能够顺利的编译!
如果内核忘记加入某个功能,而该功能可以编译成为模块,该如何是好? 如果Linux内核源码没有某个硬件的驱动程序(module),但是开发该硬件的厂商提供了Linux使用的驱动程序源码,那么又该如何将该项功能编进内核模块呢? 上面两种情况的模块编译行为是不太一样的,不过,都需要make,gcc以及内核所提供的include头文件与函数库等。
如果默认的内核没有某硬件的驱动模块,那只好自行由硬件开发商处获取驱动模块,然后自行编译! 如果你的硬件开发商有提供驱动程序的话,那么真的很好解决,直接下载该源码,重新编译, 将他放置到内核模块放置的地方后就能够使用了!
下面来为一款磁盘阵列卡(RAID)编译驱动模块,先去磁盘阵列卡官网下载驱动程序. Highpoint的RocketRAID RR640L驱动程序:http://www.highpoint-tech.com/USA_new/series_rr600-download.htm
虽然可以选择RHEL/CentOS 7 x86_64这个已编译的版本,不过由于我们的内核是自己编译的自定义内核, 还是自己来重新编译吧! 下载Open Source Driver的版本并将下载的文件放到/root/raidcard目录下. 1.将文件解压缩并且开始编译:
              [root@study ~]# cd /root/raidcard
              [root@study raidcard]# ll
              -rw-r--r--. 1 root root 501477 Apr 23 07:42 RR64xl_Linux_Src_v1.3.9_15_03_07.tar.gz
              [root@study raidcard]# tar -zxvf RR64xl_Linux_Src_v1.3.9_15_03_07.tar.gz
              [root@study raidcard]# cd rr64xl-linux-src-v1.3.9/product/rr64xl/linux/
              [root@study linux]# ll
              -rw-r--r--. 1 dmtsai dmtsai 1043 Mar 395 Dec 27 2013 Makefile
              -rwxr-xr-x. 1 dmtsai dmtsai 7 2015 config.c
              [root@study linux]# make
              make[1]: Entering directory `/usr/src/kernels/linux-3.10.89'
              CC [M] /root/raidcard/rr64xl-linux-src-v1.3.9/product/rr64xl/linux/.build/os_linux.o
              CC [M] /root/raidcard/rr64xl-linux-src-v1.3.9/product/rr64xl/linux/.build/osm_linux.o
              .....(中间省略).....
              LD [M] /root/raidcard/rr64xl-linux-src-v1.3.9/product/rr64xl/linux/.build/rr640l.ko
              make[1]: Leaving directory `/usr/src/kernels/linux-3.10.89'
              [root@study linux]# ll
              -rw-r--r--. 1 dmtsai dmtsai 1043 Mar 1399896 Oct 21 00:59 rr640l.ko 这就是生成的内核模块文件
              -rwxr-xr-x. 1 dmtsai dmtsai 395 Dec 27 2013 Makefile
              -rw-r--r--. 1 root root 7 2015 config.c
            
2.将模块放置到正确的位置:
              [root@study linux]# cp rr640l.ko /lib/modules/3.10.89initroot/kernel/drivers/scsi/
              [root@study linux]# depmod -a
              产生模块相依性文件!
              [root@study linux]# grep rr640
              /lib/modules/3.10.89initroot/modules.dep
              kernel/drivers/scsi/rr640l.ko:
              确定模块有在相依性的配置文件中!
              [root@study linux]# modprobe rr640l
              modprobe:
              ERROR: could not insert 'rr640l':No such device
              要测试加载一下才行,不过,我们实际上虚拟机没有这张RAID card,所以出现错误是正常的啦!
            
3.若开机过程中就得要加载此模块,需要将模块放入initramfs才行:
              [root@study linux]# dracut --force -v --add-drivers rr640l \
              >/boot/initramfs-3.10.89initroot.img 3.10.89initroot
              [root@study linux]# lsinitrd /boot/initramfs-3.10.89initroot.img | grep rr640
            
需要注意的是,如果内核有更新(例如利用自动更新机制进行在线更新)时,必须要重新编译一次该模块, 重复上面的步骤即可!因为这个模块仅针对目前的内核.
利用旧有的内核源码进行编译
如果你后来发现忘记加入某个模块功能了,那该如何是好?其实如果仅是重新编译模块的话, 那么整个过程就会变的非常简单!我们先到目前的内核源码所在目录执行make menuconfig, 然后将NTFS的选项设置成为模块,然后执行: make fs/ntfs/ ntfs的模块(ntfs.ko)就会自动的被编译出来了! 然后将该模块复制到/lib/modules/3.10.89initroot/kernel/fs/ntsf/目录下,再执行depmod -a,就可以在原来的内核底下新增某个想要加入的模块功能

使用SRPM文件编译内核

回到顶部

内核与内核模块是分不开的,至于驱动程序模块在编译的时候,更与内核的源码功能分不开~ 因此,你必须要先了解到:内核、内核模块、驱动程序模块、内核源码与头文件的相关性, 然后才有办法了解到为何编译驱动程序的时候老是需要找到内核的源码才能够顺利编译!
然后也才会知道,为何当内核更新之后,自己之前所编译的内核模块会失效~此外,与内核模块有相关的,还有那个很常被使用的modprobe命令, 以及开机的时候会读取到的模块定义数据文件/etc/modprobe.conf
除了使用内核官网提供的内核源码来编译内核! 也可以根据ELRepo网站提供的SRPM来重新编译打包内核!也可以直接使用ELRepo提供的CentOS 7.x专属内核来直接安装。
下面我们使用ELRepo网站提供的SRPM文件来编译内核:
大只步骤如下:
1.从ELRepo网站下载不含源码的SRPM文件,并且安装该文件
2.从www.kernel.org网站下载满足ELRepo网站所需要的内核版本来处理
3.修改内核功能
4.通过SRPM的rpmbuild重新编译打包内核就让我们来测试一下啰!(此时你应该要前往ELRepo查阅最新的SRPM之后,再决定你想使用的版本喔!)
1.下载ELRepo上面的SRPM文件!同时安装它:

              [root@study ~]# wget http://elrepo.org/linux/kernel/el7/SRPMS/kernel-ml-4.2.3-1.el7.elrepo.nosrc.rpm
              [root@study ~]# rpm -ivh kernel-ml-4.2.3-1.el7.elrepo.nosrc.rpm
            
2.根据上述的文件,下载正确的内核源码:
              [root@study ~]# cd rpmbuild/SOURCES
              [root@study SOURCES]# wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.2.3.tar.xz
              [root@study SOURCES]# ll -tr
              ......
              -rw-r--r--. 1 root root 85523884 Oct 3 19:58 linux-4.2.3.tar.xz
              -rw-rw-r--. 1 root root 294 Oct 3 22:04 cpupower.service
              -rw-rw-r--. 1 root root 150 Oct 3 22:04 cpupower.config
              -rw-rw-r--. 1 root root 162752 Oct 3 22:04 config-4.2.3-x86_64
            
3.修改内核功能设置:
              [root@study SOURCES]# vim config-4.2.3-x86_64
              #大约在5623行找到底下这一行,并在底下新增一行设置值!
              CONFIG_VFIO_PCI_VGA is not set
              CONFIG_VFIO_PCI_VGA=y
              [root@study SOURCES]# cd ../SPECS
              [root@study SPECS]# vim kernel-ml-4.2.spec
              大概在145左右找到底下这一行:
              Source0: ftp://ftp.kernel.org/pub/linux/kernel/v4.x/linux-%{LKAver}.tar.xz
              改成如下的模样:
              Source0: linux-%{LKAver}.tar.xz
            
4.开始编译并打包:
              [root@study SPECS]# rpmbuild -bb kernel-ml-4.2.spec
              #接下来会有很长的一段时间在进行编译行为,initroot的机器曾经跑过两个小时左右才编译完! #所以,请耐心等候啊!
              Wrote:/root/rpmbuild/RPMS/x86_64/kernel-ml-4.2.3-1.el7.centos.x86_64.rpm
              Wrote:/root/rpmbuild/RPMS/x86_64/kernel-ml-devel-4.2.3-1.el7.centos.x86_64.rpm
              Wrote:/root/rpmbuild/RPMS/x86_64/kernel-ml-headers-4.2.3-1.el7.centos.x86_64.rpm
              Wrote:/root/rpmbuild/RPMS/x86_64/perf-4.2.3-1.el7.centos.x86_64.rpm
              Wrote:/root/rpmbuild/RPMS/x86_64/python-perf-4.2.3-1.el7.centos.x86_64.rpm
              Wrote:/root/rpmbuild/RPMS/x86_64/kernel-ml-tools-4.2.3-1.el7.centos.x86_64.rpm
              Wrote:/root/rpmbuild/RPMS/x86_64/kernel-ml-tools-libs-4.2.3-1.el7.centos.x86_64.rpm
              Wrote:/root/rpmbuild/RPMS/x86_64/kernel-ml-tools-libs-devel-4.2.3-1.el7.centos.x86_64.rpm
              如上表最后的状态,你会发现竟然已经有kernel-ml的软件包产生了!接下来你也不需要像手动安装内核一样,得要一个一个项目移动到正确的位置去,
              只要使用yum install新的内核版本,就会有 4.2.3 版的内核在你的CentOS 7.x当中了耶!相当神奇!
              [root@study ~]# yum install
              /root/rpmbuild/RPMS/x86_64/kernel-ml-4.2.3-1.el7.centos.x86_64.rpm
              [root@study ~]# reboot
              [root@study ~]# uname -a
              Linux study.centos.initroot 4.2.3-1.el7.centos.x86_64 #1 SMP Wed Oct 21 02:31:18 CST 2015 x86_64 x86_64 x86_64 GNU/Linux
            
这样CentOS 7.x就运行在最新的内核上了!与内核官网版本相同!
总结:
内核文件包含了驱动主机各项硬件的侦测程序与驱动模块;
内核模块放置于:/lib/modules/$(uname -r)/kernel/
驱动程序开发是硬件开发厂商的工作,大部分发行版的内核编译的相当完善,对于普通用户,不太需要编译内核.
编译内核的一般目的:添加新功能、裁剪内核、与硬件搭配的稳定性.
编译内核前,最好先了解主机的硬件,以及主机的用途,才能有针对性的选择内核功能;
编译前可使用make mrproper保持内核源码的干净,可来清除暂存盘与配置文件;
使用make配合:menuconfig, oldconfig, xconfig, gconfig等选择配置内核功能与模块;
内核功能配置完毕后,一般常见的编译过程为:make bzImage, make modules;
模块编译成功后的安装方式为: make modules_install;
内核的安装过程,需要移动bzImage文件、建立initramfs文件、重建grub.cfg等;
我们可以在硬件开发商之官网下载驱动程序来自行编译内核模块!
简单说明内核编译的步骤:
1.先下载内核源码,可以从 http://www.kernel.org 或者是distributions的SRPM来着手;
2.以下以Tarball来处理,解开源码到/usr/src/kernels目录下;
3.先进行旧数据删除的动作: make mrproper;
4.开始挑选内核功能,可以利用make menuconfig、make oldconfig、make gconfig等等;
5. 清除过去的中间暂存盘资料: make clean
6.开始内核文件与内核模块的编译: make bzImage、make modules
7.开始内核模块的安装: make modules_install
8.开始内核文件的安装,可以使用的方式有: makeinstall或者是通过手动的方式复制内核文件到/boot/当中;
9.建立initramfs文件;
10.使用grub2-mkconfig 修改/boot/grub2/grub.cfg文件;
如果你利用新编译的内核来操作系统,发现系统并不稳定,你想要移除这个自行编译的内核该如何处理:
1.重新启动,并使用旧的稳定的内核开机!
2.此时才可以将新版内核模块删除: rm -rf /lib/modules/3.10.89initroot
3.删除掉/boot里面的新内核: rm /boot/vmlinuz-3.10.89initroot /boot/initramfs-3.10.89initroot.img ...
4.重建grub.cfg: grub2-mkconfig -o /boot/grub2/grub.cfg

initroot编辑整理,转载请注明www.initroot.com