精简Linux内核编译的简单方法

2019-07-13 01:38发布

【原创】精简Linux内核编译的简单方法
关于Linux内核的编译  采用先make defconfig、make menuconfig再make localmodconfig,并将后2者反复应用的过程。最后能达到比较简单的过程。基本上采取了做加法(将硬件驱动或模块依次加上,逐步改进)的思路。 
简述如下: 
1、下载源代码并建立编译工作目录和编译目标目录 
简单点,按照源码中的README文件中所述完成: 
编译工作目录:/usr/src/linux-2/6.34.1 
编译目标目录:/home/abc/build/kernel              这里/home/abc即主文件夹 
将下载的源码放到/usr/src下解压,则源码所在工作目录是/usr/src/linux-2.6.34.1 
2、编译配置(重要工作) 
可以有3种比较简单的方式对要编译进内核核心或模块的源代码进行配置。难易程度不一(需要投注的精力和时间不一样,编译生成的initrd.img-2.6.34.1、vmlinuz-2.6.34.1和System.map-2.6.34.1 
这3个主要文件的大小也不一样)。采用何种方式也可以根据需要选择如下3种方式之一对内核进行编译前的配置。 
目标:建立并得到“/home/abc/build/kernel”目录下的“.config”文件。 
(1)最简单的方式: 
将/boot下的配置文件拷贝过来使用,作为编译目标目录下的.config文件。这样对内核没有精简。 
cp /boot/config-2.6.32-21-generic ~/build/kernel/.config 
这样产生的initrd.img-2.6.34.1大概达到17M左右。不知Ubuntu采用这个配置文件怎样做到了将近8M。
(2)中等难度方式:在拷贝配置文件的基础上,使用make localmodconfig命令自动精简 
从linux-2.6.32开始可以使用make localmodconfig自动精简内核了。命令如下: 
cp /boot/config-2.6.32-21-generic ~/build/kernel/.config 
sudo make O=/home/abc/build/kernel localmodconfig 
一般说法:在运行第二条命令前,将系统的各种硬件都用一遍,以便你的系统中的模块均被调用了一次,使用“make localmodconfig”命令时,才能将你的系统将调用的模块包含进来。比方说:摄像头、U盘、光驱、SD卡等。 
如果忘了,没关系,先将上述硬件依次用一遍,再运行第二条命令一次(呵呵,重新精简,不确定的话,就将上述2条命令重新执行一遍)。 
哦,有点忘了,在第二条命令之前是否要先从.config文件中去掉一项,再使用make localmodconfig命令自动精简配置文件。如果在运行make localmodconfig命令后需要回答一些问题,而不是系统自动完成,那就按下Ctrl+c中断当前配置工作,再按照如下命令序列完成配置: 
(a)拷贝配置文件 
cp /boot/config-2.6.32-21-generic ~/build/kernel/.config 

(b)去掉“Prompt for development and/or incomplete code/drivers”项 
sudo make O=/home/abc/build/kernel menuconfig 
进入图形界面后,选择倒数第二项(Load an Alternate Configuration File)回车,弹出窗口中提示输入欲调入的配置文件名。这里默认是~/build/kernel/.config文件,无须输入任何字符,按回车即可。 
使用光标键上移到“Linux Kernel Configuration”窗口中的第一项(General Setup--->)”,按下回车,选择General setup窗口下第一项(Prompt for development and/or incomplete code/drivers),按下“N”字符键去掉这一项(将其前*去掉)。 
用向右光标键选择选项,按回车键退出当前窗口;再按向右光标键选择选项,按回车键退出当前窗口;在选择是否保存时选择“Yes”。 
(c)使用“make localmodconfig”命令自动精简内核 
sudo make O=/home/abc/build/kernel localmodconfig 
因为添加了第二个步骤(b),这时应该没什么选择了。 
使用这样配置产生的.config进行编译比配置方式(1)要精简许多,但是内核相关的3个文件还是较大。 
(3)最难(相对繁复)方式: 
先make defconfig、make menuconfig再make localmodconfig,并将后2者反复应用的过程。最后能达到比较简单的过程。 
这个过程较繁,但可望得到较简的内核。很难达到最简(除非对自己系统的硬件情况非常熟悉,并勇于实践,我们购买机器后,相对长时间内不会更换或升级硬件,所以这样的花费时间精力还是值得的),只有更简。闲话少说,上命令: 
(a)建立默认的.config文件。 
sudo make O=/home/abc/build/kernel defconfig 
本命令在文件夹“/home/abc/build/kernel”下建立一个“.config”文件。 
按照i386建立,据说是linus的配置。呵呵,还是需要对它进行增删的。以 config-2.6.32-21-generic为基础进行增删工作也可得到.config文件,但删的工作太多,容易删除不该删除的选项(再恢复就很难了,记不住也很难确定哪些该恢复)。以“make defconfig”命令建立的.config为基础增删就相对简单多了。 
(b)去掉“Prompt for development and/or incomplete code/drivers”项 
操作同2(2)(b)。 
一般说法:在运行第二条命令前,将系统的各种硬件都用一遍,以便你的系统中的模块均被调用了一次,使用“make localmodconfig”命令时,才能将你的系统将调用的模块包含进来。比方说:摄像头、U盘、光驱、SD卡等。 
如果忘了,没关系,先将上述硬件依次用一遍,再运行第二条命令一次(呵呵,重新精简,不确定的话,就将上述2条命令重新执行一遍)。 
(c)使用“make localmodconfig”命令自动精简内核 
sudo make O=/home/abc/build/kernel localmodconfig 
一般说法:在运行第二条命令前,将系统的各种硬件都用一遍,以便你的系统中的模块均被调用了一次,使用“make localmodconfig”命令时,才能将你的系统将调用的模块包含进来。比方说:摄像头、U盘、光驱、SD卡等。 
如果忘了,没关系,先将上述硬件依次用一遍,再运行第二条命令一次(呵呵,重新精简,不确定的话,就将上述2条命令重新执行一遍)。 
(d)编辑“~/build/kernel/.config”文件,添加缺失模块 
在上面(c)执行命令时,肯定会出现一些类似如下内容的信息: 
module lp did not have configs CONFIG_PRINTER 
module vgastate did not have configs CONFIG_VGASTATE 
先将它们复制粘贴到文本文件中,呵呵,然后寻找“~/build/kernel/.config”文件中对应项,例如“CONFIG_VGASTATE”,可能“~/build/kernel/.config”文件中对应的信息为: 
#  CONFIG_VGASTATE is not set 
将它改为: 
CONFIG_VGASTATE=m 
表示将这个模块包含进来。依次处理,如果找不到,没关系,先放在那儿。将上述信息中对应项都改完后保存,退出。 
(e)再次运行“make localmodconfig”命令,将(d)步骤的修改带来的变化包含进内核 
sudo make O=/home/abc/build/kernel localmodconfig 
这时系统会有一些提问。别嫌麻烦,仔细回答(如果嫌麻烦,可以全部回答m,没“m”选项时,就回答“y”。毕竟无法一次就做到非常精简---没有最简)。 
这正是本文的精彩之处,多次重用“gedit”和“make localmodconfig”命令,当然,还有后面再次使用的“make menuconfig”命令。 
(f)将(e)步骤再次出现(d)中显示的未包含模块添加进来 
如果(e)步骤中再次出现(d)中没有包含某些模块的选项,不要气馁。在编辑“~/build/kernel/.config”文件时,将相应项改为“=y”而不是“=m”。然后回到步骤(e),直到在没有模块没有包含进来的信息,或者你已经无法再减少这些信息。 
我这样做到最后,还是有如下信息: 
ricoh_mmc config not found!! 
(g)使用“make menuconfig”命令对上面得到的“~/build/kernel/.config”文件中的选项进行增删 
使用现在的.config文件进行编译,无法得到可正常运行的内核。需要注意的问题如下: 
(I)Device Drivers->Generic Driver Options--->下的2项必须选择为“y”: 
Matain a devtmpfs filesystem to mount at /dev 
   Automount devtmpfs at /dev, after the kernel mounted the rootfs 
否则,出现“Can not mount /dev”的错误。 
(II)File systems->FUSE (Filesystem in Userspace) support必须选择为“y”,否则,无法读取光驱和Windows下的分区和盘。点击Windows下的盘符时,出现如下提示信息: 
        FATAL: Module fuse not found. 
        fuse: device not found, try 'modprobe fuse' first 
(III)某些经验文档可能说了如下选项应该去掉,千万不要相信 
Enable the block layer->support for large (2TB+) block devices and files (一定要选y,否则无法读入启动文件) 
这反映了“尽信书不如无书”这句话的正确性。如果不信,实践可检验。如果此时到步骤3开始编译,得到的内核文件已经能够运行。如果还存在问题,就需要到步骤6了解有关你的机器硬件的相关信息后,再使用“make menuconfig”命令对.config文件进行增删修改,再编译安装内核。 
我的机器这样处理之后,还无法使用摄像头、访问SD卡。除此之外,如访问键盘鼠标的使用、网络、声音、显示器、U盘、Windows下的盘的访问等操作已经没有问题。 
3、编译内核 
编译内核非常简单: 
sudo make O=/home/abc/build/kernel 
如果是双核,想要加快编译速度,还可做相关设置。 
4、安装内核 
sudo make O=/home/abc/build/kernel modules_install install 
这个操作将编译的内核安装到/boot下。在Ubuntu 10.04下,会在/boot目录下产生如下文件: 
config-2.6.34.1 
System.map-2.6.34.1 
vmlinuz-2.6.34.1 
还会在/lib/modules目录下产生一个新的目录“2.6.34.1”以及其下的若干子文件夹和文件。 
但是,没有启动内核还需要的一个文件: 
initrd.img-2.6.34.1 
“initrd.img-2.6.34.1”文件通过“mkinitramfs”命令产生: 
sudo mkinitramfs -o /boot/initrd.img-2.6.34.1 /lib/modules/ 2.6.34.1 
5、修改/boot/grub/grub.cfg文件,以便启动编译好的新内核 
此时你一定急于检验编译好的内核是否能够正常启动和工作,且慢,先修改启动项: 
sudo gedit /boot/grub/grub.cfg 
将“### BEGIN /etc/grub.d/10_linux ###”下的如下信息复制并粘贴一份,然后将粘贴信息中的“2.6.32-21-generic”全部改为“2.6.34.1”即可(不要不好意思,复制粘贴就足够了)。 
menuentry 'Ubuntu, with Linux 2.6.32-21-generic' --class ubuntu --class gnu-linux --class gnu --class os { 
        recordfail 
        insmod ext2 
        set root='(hd0,7)' 
        search --no-floppy --fs-uuid --set 4b836918-3471-4fa7-85f6-79bee5970506 
        linux        /boot/vmlinuz-2.6.32-21-generic root=UUID=4b836918-3471-4fa7-85f6-79bee5970506 ro   quiet splash 
        initrd        /boot/initrd.img-2.6.32-21-generic 

重启机器,回车,用你刚才编译好的内核启动机器了。如果还有问题,你需要看步骤6、7。 
6、硬件信息的搜集 
如果想充分调动硬件并将内核精简到自己比较满意的程度,还是有必要了解自己机器的硬件信息的。 
用于了解硬件信息的命令: 
lshw                                    显示你的硬件以及所需的模块 
dmidecode                          查看硬件信息,包括bios、cpu、内存等信息 
dmesg                                 查看硬件信息 
lspci -v                                lspci (比cat /proc/pci更直观) 
/proc文件夹下的若干文件: 
cat /proc/cpuinfo                查看CPU信息 
cat /proc/meminfo                     查看内存信息 
cat /proc/bus/input/devices       查看键盘和鼠标 
cat /proc/pci                              查看板卡信息 
cat /proc/bus/usb/devices          查看USB设备 
cat /proc/interrupts                   查看各设备的中断请求(IRQ) 
uname -a                                    查看系统体系结构 
例子: lspci |grep Ethernet 查看网卡型号 
dmesg | more 
dmidecode | grep -i 'serial number' 
dmidecode -t processor 
7、再次精简内核 
按照某些经验文档,对 linux-2.6.34.1.tar.bz2 内核源文件还可如下配置,可能将来的版本应该做一些变化。 
(1')General setup->kernel compression mode改为bzip2 
(2')如果是笔记本,将General setup->kernel log buffer size改为15 
(3')去掉General setup->Control group support (按下n) 
(4')去掉Processor type and features->Enable MPS table 
(5')去掉Processor type and features->Support for extended (non-pc) x86 platforms 
(6')将Processor type and features->Processor family改为自己的处理器类型(双核均可选择core 2/newer xeon) 
(7')如果做了(6')的操作,那么去掉Processor type and features->Generic x86 support 
(8')将Processor type and features->Maximum number of CPUs改为4(双核改为4,单核改为2)
(9')去掉Processor type and features->SMT (Hyperthreading) scheduler support 
(10')如果是笔记本,将Processor type and features->Preemption model改为“Preemptible kernel (Low-Latency Desktop)” 
(11')去掉Processor type and features->AMD MCE features 
(12')去掉Processor type and features->Enable x86 board specific fixups for reboot 
(13')去掉Processor type and features->/dev/cpu/microcode-microcode support 
(14')如果内存是2G,将Processor type and features->High Memory support改为4G 
(15')只要是家用,将Processor type and features->Timer frequency改为1000HZ 
(16')将Power management and ACPI options->CPU Frequency scaling->选项下: 
        如果是笔记本,将Default CPUfreq governor改为conservative 
        将“powersave” governor、“userspace” governor for userspace  frequency scaling、“ondemand” cpufreq policy governor这3项均选上。 
        如果是Intel的CPU,将有关AMD和VIA的选项全删除。 点击打开链接
(17')去掉Networking support->Networking options->The Ipv6 protocol 
现在上网都使用IP v4,IP v6尚处于实验阶段或在某些校园网内使用。 
(18')去掉Networking support->Networking options->Asynchronous Transfer mode (ATM) 
(19')去掉Networking support->Amateur Radio support 
(20')去掉Networking support->IrDA (infrared) subsystem support 
(21')去掉Networking support->Bluetooth subsystem support 
(22')选上File systems->The extended 4 (ext4) filesystem 
(23')去掉File systems->Dnotify support 
(24')去掉File systems-> DOS/FAT/NT Filesystems-->MSDOS fs support 
(25')去掉File systems-> DOS/FAT/NT Filesystems-->Default iocharset for FAT改为“CP936”
(26')选上File systems-> DOS/FAT/NT Filesystems->NTFS file system support
(27')选上File systems-> DOS/FAT/NT Filesystems->NTFS write support
(28')去掉File systems->Miscellaneous filesystems-->
(29')去掉File systems->Network filesystems-->
(30')选上File systems->Native language support-->Simplified Chinese charset (CP936, GB2312)
(31')选上File systems->Native language support-->Traditional Chinese charset (Big5)
下面重点谈Device Drivers--->下的选择(直接驱动硬件的相关选项,步骤7搜集的信息用到这里) 
这部分根据自己的硬件,可以大刀阔斧地去掉很多,在一个大的选项下,与自己的机器对应的通常只有一、两个。 
(1')去掉SCSI device support--->SCSI tape support 
(2')去掉Multiple devices driver support (RAID and LVM)---> 
(3')去掉ISDN support---> 
(4')去掉Telephone support---> 
(5')去掉Auxiliary Display support---> 
(6')去掉X86 Platform Specifis Device Drivers---> 
其它,只能根据自己的机器选择了。例如: 
我的网卡是千兆网卡和无线网卡,只选这两样足够了: 
Network device support--->Ethernet (1000 Mbit)--->Broadcom Tigon3 support 
Network device support--->Intel Wireless Wifi---> 
Network device support--->Intel Pro/Wireless 3945ABG/BG Network connection (iwl3945)

相关话题

用户评论

m57091003 谢谢,学习了 dreamfly_cg 多谢楼主,学习学习 2351671421 不错!学习了 chunhui204 那使用make localmodconfig就意味着只能在要运行的机器上编译内核了吗? chunhui204 比如说要编译arm的内核,就要在arm上执行这条命令了