制作最小linux内核(2)

    制作最小linux内核(1) 一文中定制了一个小型内核,当重启系统加载小型内核后,往屏幕上输出"Hello world"。说实话,这样的OS并没有什么作用,至少得有个能和用户交互的界面吧?本文将继续定制内核,以实现这个目的。要实现这个目的需要2部分支持:1.继续配置内核选项以完善内核功能;2.为initrd.img增加新功能。

    1.先来完成第一部分,在这步中需要加入以下内核选项:

1.1.配置内核支持netlink。后面initrd.img中要通过udevd来动态加载模块,udevd需要这项支持:
执行make menuconfig-"Networking support"-"Networking options"-将"Unix domain sockets"编译进内核

    

1.2.配置内核支持inotify。udev使用inotify检测udev规则文件是否发生变化:

执行make menuconfig-"File systems"-将"inotify support for userspace"编译进内核


1.3.配置内核支持shell脚本。initrd.img中将执行shell脚本:

执行make menuconfig-"Executable file formats/Emulations"-将"Kernel support for scripts starting with #!"编译进内核


1.4.配置内核支持ramfs。udev挂载系统时需要用到ramfs:

执行make menuconfig-"ubuntu supplied Third-party" device drivers-将"Aufs"编译进内核;勾选"Aufs"内核项后,会出现Ramfs,同时将Ramfs(initramfs/rootfs)编译进内核


至此,内核新特性部分添加完毕,重新编译内核,并将bzImage拷贝到/boot下

$make all -j4
$sudo cp arch/x86/boot/bzImage /boot
    2.再来准备第二部分,定制initrd.img。initrd.img中包含了大量的工具,从头开始编译这些工具不是很方便,为此我找了个替代的方法:将/boot目录下ubuntu发行版的initrd.img拷贝出来,剔除一些不需要的工具和脚本,然后重新打包做成initrd.img并拷贝回/boot目录。看过前一篇文章的读者一定了解这个背景知识----initrd.img其实是经过gz压缩的cpio包。因此只要将initrd.img文件重命名为initrd.cpio.gz就能还原出其中的文件。下图是解压发行版ubuntu自带的initrd.img文件后得到的目录结构和init文件的内容:

图片中init脚本实现的功能很复杂:它实现了CDROM/网络/磁盘等多种启动方式,此外还加载了大量的驱动。这些对于我来说是不必要的,所以我对init文件做了瘦身,仅仅启动udev守护程序以及udev运行时需要挂载的sysfs/proc/ramfs等文件系统

#!/bin/sh

[ -d /dev ] || mkdir -m 0755 /dev #如果/dev目录不存在则创建 下同
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
[ -d /run ] || mkdir /run
export PATH=/bin 
mount -t devtmpfs -o mode=0755 udev /dev #挂载各类udev依赖的文件系统
mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
mount -t proc -o nodev,noexec,nosuid proc /proc
[ -e /dev/console ] || mknod -m 0600 /dev/console c 5 1 #如果不存在/dev/console设备节点则创建 下同
[ -e /dev/null ] || mknod /dev/null c 1 3
mount -n -t ramfs ramfs /run
echo > /sys/kernel/uevent_helper #uevent_helper是内核与用户层用于交互uevent事件的文件
/lib/systemd/systemd-udevd --daemon --resolve-names=never #启动udev守护程序
udevadm trigger --action=add #udevadm trigger 请求内核对全部设备模拟一遍热拔插
udevadm settle #上面的命令是个异步调用过程,settle使得脚本暂停运行,直到内核完成热拔插过程
exec /bin/sh #启动交互式sh

完成以上操作后在init同层目录下运行打包命令用以制作initrd.img

$find .|cpio -o -H newc|gzip -3 > ../initrd.img  
$sudo cp ../initrd.img /boot 

最后,定制结束后我们看下引导新内核的运行截图:

系统引导到busybox生成的shell中,而不是先前单调的输出Hello world:


运行命令,可以看到根文件系统的结构


由于udev动态产生了设备节点,因此不需要再init脚本中预设大量可能的设备节点:



  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值