一直想让 ubuntu 运行自己编译的linux kernel, 研究明白 ubuntu 的运行原理也是很迫切,因为之前 Android 系统的宝贵经验,加上 一直从事linux kernel 的工作。
实现 ubuntu customization, 不是很困难,遇到一些问题,重在静下心来把 相应的模块,以及出现的问题认真学习分析一下,让ubuntu 运行自己编译的 kernel 就成功了。
运行环境:
主机 ubuntu 11.04 + virtualbox + virtualbox_ubuntu 10.04.4.
1. 编译 linux kernel
$ make i386_defconfig
$ make menuconfig
额外配置如下:
CONFIG_DEVTMPFS = y
CONFIG_DEVTMPFS_MOUNT = y
CONFIG_EXT4_FS=y
CONFIG_EXT4_USE_FOR_EXT23=y
CONFIG_EXT4_FS_XATTR=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
如果没有这些额外配置的话,开机的时候会停留在initramfs 的命令行, 具体需要哪些额外配置还需要具体分析:
比如,可以自己先使用 i386_defconfig 重启之后出现错误的 log,分析一下就行了。
我出现的错误log 如下:
其实就是两个错误,后面的错误都是因为 mount rootfs 失败造成的。
mount: mounting none on /dev failded: No such device
mount: mounting /dev/disk/by-uuid/52429d46-26fd-4501-9670-24b880327e3b on /root failed: No such device
无非就是 devtmpfs mount 失败, rootfs mount 失败。
我真正的rootfs sda1 是ext4 文件系统,因此必须打开 EXT4 的配置,这个可以在使用ubuntu 默认的kernel 的时候就先 执行 $ mount 命令查看一下自己根文件系统的类型。
qiang@qiang-desktop:~/work/linux$ mount
/dev/sda1 on / type ext4 (rw,errors=remount-ro)
proc on /proc type proc (rw,noexec,nosuid,nodev)
none on /sys type sysfs (rw,noexec,nosuid,nodev)
none on /sys/fs/fuse/connections type fusectl (rw)
none on /sys/kernel/debug type debugfs (rw)
none on /sys/kernel/security type securityfs (rw)
none on /dev type devtmpfs (rw,mode=0755)
none on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
none on /dev/shm type tmpfs (rw,nosuid,nodev)
none on /var/run type tmpfs (rw,nosuid,mode=0755)
none on /var/lock type tmpfs (rw,noexec,nosuid,nodev)
none on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
chenqiang on /media/sf_chenqiang type vboxsf (gid=1001,rw)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev)
gvfs-fuse-daemon on /home/qiang/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=qiang)
$ make -j 32
$ sudo make install
$ sudo make modules_install
2. 制作 initramfs 镜像
可以看到/boot 目录下面的包含一个initramfs, 供 grub 配置使用。
可以先看一下 /boot/grub/grub.cfg
### BEGIN /etc/grub.d/10_linux ###
menuentry 'Ubuntu, with Linux 2.6.32-38-generic' --class ubuntu --class gnu-linux --class gnu --class os {
recordfail
insmod ext2
set root='(hd0,1)'
search --no-floppy --fs-uuid --set 52429d45-26fd-4501-9670-24b880327e3b
linux /boot/vmlinuz-2.6.32-38-generic root=UUID=52429d45-26fd-4501-9670-24b880327e3b ro quiet splash
initrd /boot/initrd.img-2.6.32-38-generic
}
menuentry 'Ubuntu, with Linux 2.6.32-38-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os {
recordfail
insmod ext2
set root='(hd0,1)'
search --no-floppy --fs-uuid --set 52429d45-26fd-4501-9670-24b880327e3b
echo 'Loading Linux 2.6.32-38-generic ...'
linux /boot/vmlinuz-2.6.32-38-generic root=UUID=52429d45-26fd-4501-9670-24b880327e3b ro single
echo 'Loading initial ramdisk ...'
initrd /boot/initrd.img-2.6.32-38-generic
}
### END /etc/grub.d/10_linux ###
$ sudo make modules_install 有如下输出:
qiang@qiang-desktop:~/work/linux$ sudo make modules_install
INSTALL arch/x86/kernel/test_nx.ko
INSTALL drivers/scsi/scsi_wait_scan.ko
INSTALL fs/ext4/ext4.ko
INSTALL fs/jbd2/jbd2.ko
INSTALL lib/crc16.ko
INSTALL net/netfilter/xt_mark.ko
DEPMOD 2.6.36
2.6.36 就是我们的 module version
$ cd /lib/modules/2.6.36
$ sudo mkinitramfs -o initrd.img-2.6.36 -v 2.6.36
制作 initramfs image, 主要 -v 就是我们的 module version.
$ sudo cp -v initrd.img-2.6.36 /boot/
3. 更新 grub 文件
qiang@qiang-desktop:/lib/modules/2.6.36$ sudo update-grub
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.36
Found initrd image: /boot/initrd.img-2.6.36
Found linux image: /boot/vmlinuz-2.6.32.60+drm33.26
Found linux image: /boot/vmlinuz-2.6.32-38-generic
Found initrd image: /boot/initrd.img-2.6.32-38-generic
Found memtest86+ image: /boot/memtest86+.bin
done
4. 重启
$ sudo reboot
开机启动的过程中要按住 shift 键,进入 grub 选择菜单。
Ubuntu 的启动分析看下 initramfs 中 init shell 脚本就行了。
$ mv initrd.img-2.6.36 -v 2.6.36 initrd.img-2.6.36 -v 2.6.36.gz
$ gunzip initrd.img-2.6.36 -v 2.6.36.gz
$ mkdir initrd.img.dir
$ cpio -i < ../initrd.img-2.6.36 -v 2.6.36
参考文章:

本文详细介绍如何在Ubuntu上编译并安装自定义的Linux内核,包括必要的配置选项、解决常见问题的方法以及如何创建和更新initramfs镜像。
2768





