Linux下编译最新内核

Linux下编译最新内核

编译内核的通用方式

复制内核

复制原有的/boot/config-2.6.18-128-el5,到/usr/src/linux-xxxx源码目录下,名字为.config

cp /boot/config-2.6.18-128-el5 .config 

配置内核选项

修改内核选项,这个过程其实就是修改.config文件,因为上一步的原因,所以里面的大部分选项不需要修改,当然你可以修改来精简自己的内核,这一步里主要做的就是增加自己需要的属性,要么[*],要么[M].

make menuconfig

make menuconfig

Device Drivers

Device Drivers

ATA Device Support

ATA Device Support

SCSI Device Support

SCSI Device Support

Serial ATA Device Support

SATA Device Support

编译内核及打包

利用下面的一连串的命令就把内核编译了一遍,如果是Redhat系列的,下一步就可以直接reboot了,它已经把grub,initrd等都搞定了;若是debian系列的,可能还需要一些额外的操作,比如update-grub,update-initramfs之类的.

make;
make modules;
make modules_install;
make install

重新启用内核

reboot

常见问题及解决方案

掌握最新编译选项的含义

Device Drivers非常注意

CONFIG_IDE_GD=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=m

GCC版本过低导致错误

drivers/built-in.o(.init.text+0x3bad): In function `con_init': 
include/trace/events/kmem.h:47: undefined reference to `.L1452'

解决:

vi /usr/src/linux/drivers/char/vt.c 

删除以下行 ( 第 2875 行 )

vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);   

在相同位置添加 :

vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data)); 

再在前端头部添加

#include <linux/bootmem.h> 
后来发现,此错误是由gcc版本过低引起的。旧gcc版本为gcc version 3.4.6,换成新的gcc version 4.1.2即可。

GCC升级/GCC编译

yum install -y gcc-c++ autoconf automake bison textinfo bzip2 glibc-devel.x86_64
 
wget  https://mirrors.ustc.edu.cn/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz
xz -d gcc-8.4.0.tar.xz 
tar xvf gcc-8.4.0.tar 
 
cd gcc-8.4.0/
sh download_prerequisites 
 
cd gmp-6.1.0/
./configure --prefix=/opt/gmp61
make -j4 install
 
cd mpc-1.0.3/
./configure --prefix=/opt/mpc103
make -j4 install
 
cd mpfr-3.1.4/
./configure --prefix=/opt/mpfr314
make -j4 install
 
cd isl-0.18/
./configure --prefix=/opt/isl
make -j4 install
ln -snf /opt/isl/lib/libisl.so.15 /lib64/
 
./configure --prefix=/opt/gcc84 \
            --with-isl=/opt/isl \
            --with-mpc=/opt/mpc103 \
            --with-mpfr=/opt/mpfr314 \
            --with-gmp=/opt/gmp61 \
            --enable-languages=c,c++ \
            --disable-multilib
注意:不要去编译升级gcc,编译升级后可能会给你带来额外的麻烦。

devtoolset 是受Red Hat 的支持维护的工具集合,包含了GCC(C/C++/Fortan),GDB,Valgrind,Make 等等一些常用的开发和调试工具。

devtoolset-3对应gcc4.x.x版本
devtoolset-4对应gcc5.x.x版本
devtoolset-6对应gcc6.x.x版本
devtoolset-7对应gcc7.x.x版本
devtoolset-8对应gcc8.x.x版本
devtoolset-9对应gcc9.x.x版本
devtoolset-10对应gcc10.x.x版本
默认的GCC 版本无法无法编译 Glibc 2.28。 安装GLIBC所需的依赖,该版本需要 GCC 4.9 以上 及 make 4.0 以上。 GCC 11.2版本太新,无法与Glibc 2.28兼容。

nash版本不兼容

在我们刚刚取得基本成功的时刻,恰逢 Linux 2.6.32 正式版内核发布,要不在正式版内核上也实验一下吧。既然上面是因为升级 nash 而最终成功的,那么 dm-raid45 有可能不是核心问题所在。因此在编译正式版内核时,我们没有加入 dm-raid45,而只替换了 nash 版本。结果一次就启动成功!看来这个问题真是 nash 引起的。至于 dm-raid45,这个机器使用的是硬件 RAID 卡,对操作系统透明,一般不需要内核支持;而 dm-raid45 是软 RAID 模块(感谢网友指正),对我们的系统来说安装不安装无所谓。

新旧sysfs路径不兼容

今天 google 到了另一种解决方案:编译内核前,在 .config 中设置“CONFIGSYSFSDEPRECATEDV2=y”即可。经我们实验,果然如此。究其原因,google 到的答案[1][2]大约是说旧版的 mkinitrd 及其 nash 在内核没有 CONFIGSYSFSDEPRECATED_V2 参数时默认使用旧版 sysfs 路径格式,从而在新内核下无法正确访问 /sys 内的硬盘信息节点。 </blockquote> ==== 如何重新打包initrd.img ==== === 解开原镜像包 === <code bash> [root@localhost newdir]# zcat ../initrd-2.6.32.2.img | cpio -id 15243 blocks </code> === 修改后重新打包 === <code bash> [root@localhost newdir]# find | cpio -c -o > ../initrd.img.xxxx [root@localhost newdir]# gzip -9 < ../initrd.img.xxxx > ../initrd.img </code>

注意:必须要带-c参数

-c : Use the old portable (ASCII) archive format. 

==== Clock skew detected报错 ==== 修改系统的日期与时间然后重新编译安装。则错误消失。 如果马上重起机器,修改时间就有可能没有被写入CMOS,这就是问题的原因。如果要确保修改生效可以执行如下命令。 <code bash> #clock -w </code> 这个命令强制把系统时间写入CMOS。 ====CPU hotplug==== 近日在DELL PowerEdge R510 服务器上安装CentOS 4.8 编译linux-2.6.16.62 ,内核中加入SMP 支持,开机重启
提示错误如下 weird, boot CPU (#0) not listed by the BIOS Booting processor 1/32 eip 2000 CPU 1 irqstacks, hard=c040d000 soft=c03cd000
在GRUB命令行添加nosmp 参数之后,可以启动系统,但只能使用单核心 。 解决方法:编译内核时 加入CPU hotplug 支持 processor type and features→ support for hot-pluggable CPUS(EXPERIMENTAL) ====Linux 2.6.32 hwclock ==== Linux 2.6.32.27 Device driver –> Real Time Clock–> /dev/rtcN(character devices) CONFIG
RTCINTFDEV:

Say yes here if you want to use your RTCs using the /dev
interfaces, which “udev” sets up as /dev/rtc0 through
/dev/rtcN.

You may want to set up a symbolic link so one of these
can be accessed as /dev/rtc, which is a name
expected by “hwclock” and some other programs. Recent
versions of “udev” are known to set up the symlink for you

旧版本的UDEV 无法自动生成 /dev/rtc0 到/dev/rtc 的软连接 。导致hwclock 无法工作.

解决方法

  1. ln -snf /dev/rtc0 /dev/rtc
  2. 升级udev

==== Early Retransmit for TCP原理以及实现 ====

我们可以看到ER打开的三个条件分别是

  • 首先sysctl的选项必须打开
  • 第二thin dupack必须关闭
  • 第三tcpreordering必须为3 <blockquote> tcpearly_retrans – INTEGER Enable Early Retransmit (ER), per RFC 5827. ER lowers the threshold for triggering fast retransmit when the amount of outstanding data is small and when no previously unsent data can be transmitted (such that limited transmit could be used). Possible values: 0 disables ER 1 enables ER 2 enables ER but delays fast recovery and fast retransmit by a fourth of RTT. This mitigates connection falsely recovers when network has a small degree of reordering (less than 3 packets). Default: 2 </blockquote>
/proc/sys/net/ipv4/tcp_thin_dupack  0
/proc/sys/net/ipv4/tcp_reordering   3
/proc/sys/net/ipv4/tcp_early_retrans  3
/proc/sys/net/ipv4/tcp_frto 2

==== error getting socket: Address family not supported by protocol ====

“CONFIGUNIX”是为了配置“Unix domain sockets”的,“CONFIGUNIX”一般都是应该配置为y(编译进kernel),如果只有在少数(如嵌入式)系统中才配置为m(作为module,名为”unix”的module)。即是没有连接到任何网络,有很多常用的程序都使用“unix domain socket”进行通信的,如X-Window、syslog等程序,估计还有我本例遇到的udevadm(udevd)等程序,都是依赖于“CONFIG_UNIX=y”这个配置的。

==== FATAL: Module scsiwaitscan not found ====

关于“FATAL: Module scsiwaitscan not found.”这个错误,应该在kernel config中配置“CONFIGSCSISCANASYNC=y”,如果有“CONFIGSCSIWAITSCAN”则也应该配置“CONFIGSCSIWAIT_SCAN=m”。

Linux 3.6中已经没有CONFIGSCSIWAITSCAN配置项可选了,后来发现guest的grub中的root设备写法的问题(这时不能写成/dev/sda1)。出现问题的grub中kernel行如下: kernel (hd0,0)/boot/vmlinuz-3.6.0 ro root=/dev/sda1 修改为UUID的方式去找到root设备,就没有“FATAL: Module scsiwait_scan not found.”错误,可以正常启动了。

CentOS 6 will not boot on KVM with elrepo kernel 3.13 / 3.14

When using elrepo and installing the kernel-ml package, you may find your system will not boot. The console will display “module scsiwaitscan not found”

yum install -y device-mapper-libs libudev
for X in $(cd /boot ; ls -1 config-*elrepo* | sed 's/config-//' ) ; do dracut --add-drivers virtio_blk -f /boot/initramfs-$X.img $X ; done

==== 利用Dracut重新生成initrd镜像 ====

# dracut --force --add-drivers "hpsa mpt3sas megaraid ses smartpqi megaraid_sas" initramfs-with-mymod.img
dracut-initqueue timeout
很有可能就是因为没有加载 sas 模块,导致找不到 root 根目录

==== 如何单独编译和加载内核模块 ====

一次偶然的机会,需要加载一个新的gre模块,只能重新编译模块,加载

make modules

会产生ip_gre.ko 和 Module.symvers的符号表的更新

wiki/public/linux/定制linux操作系统内核.txt · 最后更改: 2025/11/21 00:34