认识内核
kernel是整个操作系统最底层,它负责了整个硬件的驱动,以及提供各种系统所需的核心功能,包括防火墙机制,是否支持LVM或者Quota等文件系统,这些都是内核负责。计算机正在工作的是硬件,但是,你希望计算机帮你达成各项工作,都需要透过内核帮助才能执行,当然如果你要达成的工作核心不支持,那么你自然无法透过内核来控制计算机来工作。内核就是一个文件,可以实现上面诸多功能。
内核模块
既然内核都已经包含了硬件侦测与驱动模块,那什么是内核模块,现在计算机硬件更新速度太快,如果我的核心比较旧,但我换了新的硬件,那么kernel肯定无法支持,而linux很早之前就开始模块化设定,亦即是将一些不常用过的类似驱动程序独立出来,编译成为模块,然后kernel可以在系统正常运行的过程中加载这个模块到kernel以支持模块的使用。
自制kernel-kernel编译
kernel是一个文件,这个文件时透过哦source code编译而成的,应为内核是直接被写入到内存当中,所以当然要将他编译成为系统可以认识的数据才行。也就是说我们要获得kernel的源码。
更新内核的目的
除了BIOS之外,内核是操作系统最早被加载到内存,他包含了所有可以让硬件与软件工作的信息,所以如果内核有问题,那么操作系统肯定会出现问题。kernel的编译重点在于你要你的linux做什么,如果没有必要的工作,就干脆不要加入内核中。kernel编译的可能目的如下: 新功能的需求,原本内核太过雍宗,与硬件搭配的稳定性,其他如嵌入式。
内核源码的解压缩/安装/观察
#第一步取得内核源码:
[root@localhost]# wget linux.cis.nctu.edu.tw/kernel/linux/kernel/v2.6/linux-2.6.30.3.tar.bz2
#解压缩内核
[root@localhost]# tar -jxvf linux-2.6.30.3.tar.bz2 -C /usr/src/kernels/
此时会在/usr/src/kernel目录下产生一个新的目录,linux-2.6.30.3,在这个目录下包含以下数据:
[root@localhost linux-2.6.30.3]# ls
arch crypto fs Kbuild Makefile REPORTING-BUGS sound
block Documentation include kernel mm samples usr
COPYING drivers init lib net scripts virt
CREDITS firmware ipc MAINTAINERS README security
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)
1. 硬件环境检视与内核功能要求
[root@localhost linux-2.6.30.3]# cat /proc/cpuinfo
vendor_id : GenuineIntel
cpu family : 6
model : 69
model name : Intel(R) Core(TM) i5-4310U CPU @ 2.00GHz
[root@localhost linux-2.6.30.3]# lspci
00:00.0 Host bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (rev 01)
00:01.0 PCI bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge (rev 01)
00:07.0 ISA bridge: Intel Corporation 82371AB/EB/MB PIIX4 ISA (rev 08)
00:07.1 IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)
00:07.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08)
编译目的主要是加深对内核的认识,以及熟悉内核编译过程,所以为了省事,我这里就按照最简单的方法来进行。第一次进行编译,我们还不清楚下载下来的源码当中有木有保留目标文件(*.o)以及相关的配置文件的存在,此时我们可以透过一下的方式出路掉这些编译过程的目标文件以及配置文件
[root@www linux-2.6.30.3]# make mrproper
请注意这个动作会将你以前进行过的内核内核功能选择文件也删除,所以几乎只有在第一执行内核编译的时候才进行这个操作,其余时刻只要删除前一次编译过程的残留数据
[root@www linux-2.6.30.3]# make clean
[root@localhost linux-2.6.30.3]# make menuconfig
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/kxgettext.o
*** Unable to find the ncurses libraries or the
*** required header files.
*** 'make menuconfig' requires the ncurses libraries.
***
*** Install ncurses (ncurses-devel) and try again.
***
make[1]: *** [scripts/kconfig/dochecklxdialog] Error 1
make: *** [menuconfig] Error 2
#这里大家看到我遇到了一些问题,缺少函数库或者ncurses-devel文件,我用yum下载一下
[root@localhost linux-2.6.30.3]# yum install ncurses
#在执行就可以了,大家注意一定要最大化窗口,在执行命令,不然会报错的
cp /boot/config-2.6.32-431.el6.x86_64 /usr/src/kernels/2.6.32-431.el6.x86_64/.config
然后就可以在此的基础上使用make menuconfig命令进行模块的选择,我这里就不在详细显示,我在这里简单的介绍一下怎么选择大概用法如下:
选定项目:以上下键选择好想要设定的项目之后,按【enter】
就可以进入该项目去做跟一步的详细操作
可挑选功能:只有前面有[]和<>符号时,该项目才可一选择,选择使用空格键
若为[]<>则表示编译进内核,若为则表示编译为模块,在不知该项目为何时,且有模块可选,尽量选择模块。
总之,尽量保持内核小而美,剩下的功能就编译为模块,选择好配置后我们保存退出,开始进行编译工作。
[root@localhost linux-2.6.30.3]# make
#首先是make命令进行编译,接着就是漫长的编译情况,
编译内核,为了加快编译速度,可以添加选项-jn,其中n替换为线程数值,一般是CPU核数的两倍。
make -j8 all
安装内核模块。
make modules_install
note:其实在make all和make modules_install中间还有两条命令可以操作,就是make bzImage(压缩内核)和make modules(编译模块),但是这两条命令无关紧要,可以不管。
将编译生成的内核文件拷贝到对应位置去,其实可以很简单就用make install命令即可,只是会自动添加一些其他东西上去,我这里就使用最简单的方法,会在下面列出手动安装的方法。
[root@localhost linux-2.6.30.3]# make modules_install
..............
[root@localhost linux-2.6.30.3]# make install
sh /usr/src/kernels/linux-2.6.30.3/arch/x86/boot/install.sh 2.6.30.3 arch/x86/boot/bzImage \
System.map "/boot"
ERROR: modinfo: could not find module nf_defrag_ipv6
ERROR: modinfo: could not find module vmhgfs
ERROR: modinfo: could not find module vsock
ERROR: modinfo: could not find module vmware_balloon
ERROR: modinfo: could not find module vmci
#发现有报错,但是这里我就忽略不管了,下面查看内核是否已经安装好
[root@localhost linux-2.6.30.3]# cat /etc/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/sda2
# initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=2
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.30.3)
root (hd0,0)
kernel /vmlinuz-2.6.30.3 ro root=UUID=f9c1daa0-3b5c-4543-8fda-79a2283c1d06 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.30.3.img
title CentOS (3.18.12-11.el6.x86_64)
root (hd0,0)
kernel /xen.gz dom0_mem=256M,max:512M loglvl=all guest_loglvl=all
module /vmlinuz-3.18.12-11.el6.x86_64 ro root=UUID=f9c1daa0-3b5c-4543-8fda-79a2283c1d06 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
module /initramfs-3.18.12-11.el6.x86_64.img
title CentOS (2.6.32-431.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=UUID=f9c1daa0-3b5c-4543-8fda-79a2283c1d06 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-431.el6.x86_64.img
#内核已经安装好了,我先不在这里修改了,启动后手动修改启动内核,看是否能启动
#通过选择启动内核发现已经起来,查看内核版本
[root@localhost ~]# uname -r
2.6.30.3
#起来后机器有报错误,可能是那几VMware模块的问题
下面介绍一起手动安装的方法(转载自他人):
将编译生成的内核文件拷贝到对应位置去,其实可以很简单就用make install命令即可,只是会自动添加一些其他东西上去,故未采用。
cp -v System.map /boot/System.map-2.6.34.14
cp -v arch/i386/boot/bzImage /boot/vmlinuz-2.6.34.14
cp -v .config /boot/config-2.6.34.14
rm -f System.map vmlinuz
ln -s vmlinuz-2.4.18 vmlinuz
ln -s System.map-2.4.18 System.map
注:
其实除了cp -v arch/i386/boot/bzImage /boot/vmlinuz-2.6.34.14是必须的之外,其余的操作可以不管。
为新内核创建一个ramdisk,否则系统不能引导。
mkinitrd /boot/initramfs-2.6.34.14.img 2.6.34.14
PS:后面的2.6.34.14是根据版本来填的,具体可以依据/lib/modules目录里面的目录名来填。
如果不创建ramdisk,很容易遇到一个这样的报错:
VFS:Cannot open root device “sda” or unknow-block(0,0)
Please append a correct “root=” boot option
kernel panic:VFS:Unable to mount root fs on unknown-block(0,0)
很让人头疼的,就这玩意折腾了我N个小时了。
配置grub信息。
vim /etc/grub.conf
新增内容:
title CentOS (2.6.34.14)
root (hd0,0)
kernel /boot/vmlinuz-2.6.34.14 ro root=UUID=5ee1b1da-0889-47c0-ae3f-13b64bafeb28
initrd /boot/initramfs-2.6.34.14.img
PS;root=UUID=5ee1b1da-0889-47c0-ae3f-13b64bafeb28,这个是对系统上已有的grub配置“抄袭”过来的,别照搬~至此为止,已经搞定了。
reboot
复位系统开始引导新内核。
额外单一内核模块的编译
我们知道内核支持的功能当中,直接编译到内核内部的,也有使用外挂模块的,外挂模块可以简单的相处就是驱动程序,内核模块依据不同的版本,被分配/lib/modules/ (uname−r)/kernel/目录中,各个硬件的驱动程序则是放置到/lib/modules/ (uname -r)/kernel/drivers/当中。加入我们编译过程中,忘记将某个驱动加载进去,或者硬件厂商发布新的驱动程序怎么办:由于我们的内核版本就是提高内核工具给硬件开发商使用过,而硬件开发商也需要针对内核所提高的功能来设计他们的驱动程序模块,因此,我们想要使用硬件开发商提高的模块进行编译时,就需要使用过内核提高的原始文件当中,所谓头包含文件(header inlude file)来驱动驱动模块所需的一些函数库的定义,如果如果需要自行编译模块时,就必须的要拥有原始码。由亍核心模块的编译其实不核心原本的原始码有点关系的,因此如果你需要重新编译模块时, 那除了 make, gcc 等主要的编译软件工具外,你还需要的就是 kernel-devel 这个软件!让得一定要安装喔!而如果你想要在预设的核心底下新增模块的话,那举就得要找到 kernel的 SRPM 档案了! 将该档案给他安装,并且取得 source code 后,才能够顺利的编译喔!