Chinaunix首页 | 论坛 | 博客
  • 博客访问: 209631
  • 博文数量: 57
  • 博客积分: 1694
  • 博客等级: 上尉
  • 技术积分: 481
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-26 16:26
文章分类

全部博文(57)

文章存档

2011年(2)

2010年(37)

2009年(18)

我的朋友

分类: LINUX

2009-12-19 17:25:38

1.基础知识

一个操作系统可以简单的抽象为,引导程序 内核 文件系统。

vmlinuz是Linux 内核的镜像文件,可以被引导程序加载,从而启动Linux系统。

initrd的全称是boot loader initialized RAM disk,它是系统启动时所使用的根文件系统映像文件,这个文件系统中包含几个驱动模块,用来装载实际的根文件系统,比如一个IDE或SCSI硬盘的驱动模块,内核装入这个模块之后用它来驱动硬盘,挂接硬盘到ramdisk的某个子目录,然后再用其中的pivot_root命令,将硬盘文件系统变成根文件系统,并开始执行init进程,此时init ram disk被umount,寿终正寝。

由此可见,我们可以用vmlinuz initrd.img做一个文件系同长驻内存的迷你Linux。

现在进入正题了:

 

2.编译内核

cd /usr/src/....----进入内核源代码目录,没有的话去官方网站,随便下

make menuconfig-----配置编译选项请注意一定加入RAM disk support 和initial RAM disk

(initrd) support 的支持(在block device中)。另外最好将ext3文件系统编入内核,不要编成模块。配置完毕后保存为.config(默认)

make bzImage----编译

 

在许多内核编译参考中还有

make modules

make modules_install两步

但我们这里没有加入对modules的支持,所以不需要。生成的bzImage文件在usr/src/linux/arch/.../boot中,省略的根据你的机器架构决定,make过程中会有提示,比如我的是x86_64. 注意这个文件非常重要,其实就是我们最终的vmlinuz.

 

(我们做的就没有上面两步,也能成功,大家注意要把许多东西编译到内核里才能用,如把网卡、磁盘驱动等,还有一些系统命令如果内核里没有的话不支持,如:mount、brctl等。如还有一种方法就是在一个完整的OS上查看一些软件所依赖的库函数,然后再打到ramdisk的对应目录)如下例:

[root@localhost zhxue]# which brctl
      /usr/sbin/brctl
      [root@localhost zhxue]# ldd /usr/sbin/brctl
        linux-gate.so.1 =>  (0x009ad000)
        libsysfs.so.2 => /usr/lib/libsysfs.so.2 (0x00abd000)
        libc.so.6 => /lib/i686/nosegneg/libc.so.6 (0x00110000)
        /lib/ld-linux.so.2 (0x00909000)

 

 

3.busybox

busybox是一个集成了一百多个最常用linux命令和工具的软件,它甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小.我们平时用的那些linux命令就好比是分力式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍,在嵌入式linux应用中,busybox有非常广的应用,另外,大多数linux发行版的安装程序中都有busybox的身影,安装linux的时候案ctrl alt F2就能得到一个控制台,而这个控制台中的所有命令都是指向busybox的链接.在我们的迷你Linux中,需要的也正是busybox的命令和工具。

 

下载

使用过程中许多高版本都出现编译错误,所以用了一个最原始的版本busybox-1.00

#cp busybox-1.00.tar.gz /tmp/bunny

#cd /tmp/bunny

#tar xvfz busybox-1.00.tar.gz

#cd busybox-1.00

#make menuconfig ----编译配置

 

下面是需要编译进busybox的功能选项,其他的可以根据需要自选.

General Configuration应该选的选项

Show verbose applet usage messages

Runtime SUID/SGID configuration via /etc/busybox.conf

Build Options

Build BusyBox as a static binary (no shared libs)

 

这个选项是一定要选择的,这样才能把busybox编译成静态链接的可执行文件,运行时才独立于其他函数库.否则必需要其他库文件才能运行,在单一个linux内核不能使他正常工作.

 

Installation Options

Don't use /usr

 

这个选项也一定要选,否则make install 后busybox将安装在原系统的/usr下,这将覆盖掉系统原有的命令.选择这个选项后,make install后会在busybox目录下生成一个叫_install的目录,里面有busybox和指向它的链接.

 

其他选项都是一些linux基本命令选项,自己需要哪些命令就编译进去,一般用默认的就可以了.

配置好后退出并保存.config.

make

make install

编译好后在busybox目录下生成子目录_install,里面的内容:

bin

linuxrc -> bin/busybox

sbin

其中可执行文件busybox在bin目录下,其他的都是指向他的符号链接.

 

4.制作自己的root fs

1)目录结构

mkdir /tmp/myOS/rootfs

cd /tmp/myOS/rootfs

mkdir etc usr var tmp proc home root dev

其中etc,proc和dev是一定要建的,bin和sbin不用建,因为busybox中已经有了.

其他的可以象征性的建几个就可以了.

拷贝busybox

#cp -R /tmp/bunny/busybox-1.00/_install/* /tmp/myOS/rootfs/

 

2)设备文件

我是直接从FC系统/dev目录里cp的,方法如下:

#cp -R /dev/console /tmp/myOS/rootfs/dev/

#cp -R /dev/null /tmp/myOS/rootfs/dev/

#cp -R /dev/zero /tmp/myOS/rootfs/dev/

你认为需要的都cp过来

有的参考文献说fd0,hda,ram,ram1,tty1,loop1,fb0,fb,tty等是必备的,但是好像有些文件并没有

 

3)建立etc目录下的配置文件

我是直接拷贝busybox自带的例子

cp -R tmp/bunny/busybox-1.00/examples/bootfloppy/etc/* /tmp/myOS/rootfs/etc

 

4)制作initrd.img映象文件

2.6之前是这样做的

cd /tmp/myOS/

dd if=/dev/zero of=/tmp/disk bs=1M count=32 ------初始化32M内存空间

mkfs.ext3 -m0 /tmp/disk ------格式化为ext3

mkdir /mnt/ram

mount -o loop /tmp/disk /mnt/ram ------挂载到/mnt/ram

cp -R rootfs/* /mnt/ram ------把rootfs写入内存

umount /mnt/ram

dd if=/tmp/disk of=/tmp/myOS/initrd.img ------把内存中的内容以映象方式取出

ok,这个initrd.img就是我们的rootfs

有的文献使用ram0,也就是将上述过程的/tmp/disk改为/dev/ram0,虽然制作过程没有问题,但是它存在大小限制

 

我们是这样做的:

 

cd /mnt/myOS/
dd if=/dev/zero of=/dev/ram0 bs=1M count=4    ------初始化4M内存空间   //这一步可以改一改:否则img最大只能为4M, of=/tmp/myimg bs=1M count=32
mkfs.ext3 -m0 /dev/ram0                                        ------格式化为ext3
mkdir /mnt/ram
mount /dev/ram0 /mnt/ram                                    ------挂载到/mnt/ram
cp -R rootfs/* /mnt/ram                                           ------把rootfs写入内存
umount /mnt/ram
dd if=/dev/ram0 of=/mnt/myOS/ramdisk.img     ------把内存中的内容以映象方式取出
   主要是使用ram0而不是自己建一个,但是这样做出来的东西始终都是17M左右,count=8,16,32,都一样,我不知道是不是和我们使用了ram0有关,以后可以试验一下,不要用ram0,自己随意创建一个目录。

经过同事的实验,这个问题有答案了。 还是老办法,原来是用/dev/ram0,现在我用dd /tmp/ram0。 看文档,/dev/ram0,开机后大小就确定了。 在tmp下建立的大小是按照我们要求的

 

dd if=/dev/zero of=/tmp/ram0 bs=1M count=4
      mkfs.ext3 -m0 /tmp/ram0
      mount -o loop /tmp/ram0 /mnt/ram/
      cp -R rootfs/* /mnt/ram/
      umount /mnt/ram/
      dd if=/tmp/ram0 of=rootfs.img

 

2.6以后是这样做的(实践证明似乎下面做法的initrd无法使用,提示无法找到root fs)

      2.6内核中的initrd.img采用cpio压缩,不再是2.4内核使用的ext2格式,无法使用mount -o loop 挂载。需要使用gunzip解压缩,然后再使用cpio解包

cp /boot/initrd-***.img initrd.img.gz
gunzip initrd.img.gz
mkdir initrd
mv initrd.img initrd
cd initrd
cpio -ivmd < initrd.img

通过以上命令就将initrd.img解压了,现在就可以对其进行编辑,完成后使用以下命令重新压制

find . | cpio -ov > ../initrd.new.img
gzip ../initrd.new.img

再将其改名拷贝至/boot目录,重启就可以观察修改后的效果

IBM Linux社区的一篇强贴http://www.ibm.com/developerworks/cn/linux/l-k26initrd/

 

5.整合,启动

1)kernel

cp /usr/src/linux/arch/x86_64/bzImage /boot/vmlinuz

2)rootfs 一般命名为initrd.img

cp /tmp/myOS/initrd.img /boot

3)有了上述两个文件,已经可以通过网络dhcp, tftp服务器启动,tftp服务器中添加启动脚本如下pxelinux.cfg/default文件

DEFAULT linux

PROMPT 0

LABEL linux

KERNEL vmlinuz

append initrd=initrd.img devfs=nomount ramdisk_size=52000 (devfs和ramdisk_size两个可以不用指定)

 

另外还有一些指定方式很灵活:

 

 

后续工作 

 

ramdisk启动成功后,我想把根文件系统切换到另一个地方(NFS),可以用pivot方法,为了自动化这个过程,我把这些东西放到了busybox中的/etc/init.d/rcS里,busybox的linuxrc会自动执行这个脚本。脚本如下:

 

#! /bin/sh

/bin/mount -a
      mkdir /mnt
      ifconfig eth0 192.168.100.3 netmask 255.255.255.0 up
      mount -o nolock 192.168.100.35:/sdb/root /mnt
      pivot_root /mnt  /mnt
      sh /etc/rc.d/rc.sysinit

 

上述脚本中,最后一步本应该为 /sbin/init但执行它老是跑出init:unable to send message的错误。于是我看了一下/sbin/init的启动过程了解了其执行步骤,于是我把这些步骤拆开做。这些步骤主要包括:

​首​先​,它​运​行 /etc/rc.d/rc.sysinit 脚​本​,这​会​设​置​环​境​路​径​、​启​动​交​换​空​间​、​检​查​文​件​系​统​并​执​行​所​有​系​统​初​始​化​所​需​的​其​他​步​骤​。

然​后​,init 命​令​运​行 /etc/inittab 脚​本​,这​描​述​了​系​统​在​每​个 SysV init 运​行​级​别​ 应​该​怎​样​设​置​。​运​行​级​别​(runlevel)是​一​个​状​态​,或​者 模​式​,它​由 SysV /etc/rc.d/rc.d/ 目​录​里​列​出​的​服​务​来​定​义​(在​这​里​, 是​运​行​级​别​)。​

init会根据/etc/inittab脚本的内容进行执行,基本上就结束了

接​着​,init 命​令​为​系​统​设​置 source function library,/etc/rc.d/init.d/functions,配​置​怎​样​启​动​、​杀​死​和​决​定​程​序​的​进​程​号​(PID)。

 

理解chroot   http://www.ibm.com/developerworks/cn/linux/l-cn-chroot/index.html

 我发现pivot_root切换根目录后,/dev/ram0下的东西仍然是busybox的,就是我们自己做的img的
 可以把/dev/ram0挂到/mnt上,然后在pivot_root切回去
 理论上这样子可以关机了,但是我做的内核和img可能有些问题

还有一种实验成功的办法,当根文件系统切换到NFS上的文件系统成功后,用yum把busybox重新安装了一下,然后再执行busybox poweroff。关机成功

 

关于 initrd 资料:

http://www.ibm.com/developerworks/cn/linux/l-initrd.html

http://www.ibm.com/developerworks/cn/linux/l-k26initrd/

阅读(1286) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~