[TED] 创建自己的ramfs (二)

来源:互联网 发布:c语言中数组的定义 编辑:程序博客网 时间:2024/05/18 03:45

上一次我们说到如何用buildroot建立ramfs,虽然buildroot方便好用但是因为采用uClinux所以如果遇到必须用LIBC的情况就得另辟蹊径了。这次我们化整为零,从busybox开始构建自己的ramfs,首先我们先弄清楚


1) 首先创建一个文件夹作为你的ramfs根目录,我们暂定为/home/myroot


2) 现在在myroot下 已经有 /usr/sbin,  /usr/bin,  /sbin,  /bin

我们还要创建其他几个目录

mkdir dev etc home lib proc root sys var tmp


3) 拷贝当前/lib下的文件到/myroot/lib之下,这里要特别注意必须保证/myroot/下lib的目录结构和编译机器上完全一致

否则会导致启动时候报错所谓找不到文件,其实就是对应的库文件没找到。 比如我的编译机上库文件在lib64/ld-linux-x86-64.so.2

就必须在/myroot目录下同样有lib64/ld-linux-x86-64.so.2其他也是必须一一对应。


4) 添加启动脚本

在根目录下创建一个init文件(别忘了修改属性为可执行),它是ramfs被加载后第一个被调用的脚本,内容如下:


#!/bin/sh# devtmpfs does not get automounted for initramfs/bin/mount proc /proc -t proc/bin/mount sys  /sys -t sysfs/bin/mount -t tmpfs tmpfs /dev/bin/mkdir -m 0775 /dev/pts/bin/mount devpts /dev/pts -t devpts/sbin/mdev -sexec 0</dev/consoleexec 1>/dev/consoleexec 2>/dev/console/bin/sh

如果你想创建一个简单的ramfs,那么到此为止这个ramfs就已经大功告成了。它已经具备了一个ramfs最基本的服务和功能。

如果你需要的是一个具备一定功能的ramfs比如网络,账户和安全登陆那我们还需要继续往下走。

这个根目录下的脚本也得改一改,把大部分功能都按照规范放在后面再执行

#!/bin/sh# devtmpfs does not get automounted for initramfs/bin/mount -t devtmpfs devtmpfs /devexec 0</dev/consoleexec 1>/dev/consoleexec 2>/dev/consoleexec /sbin/init $*

最后这里调用了/sbin/init 这个文件也是busybox的马甲,它的工作如下:

1) 配置console

2) 设置环境变量(HOME, sbin, bin, usr/sbin, usr/bin, SHELL=/bin/sh, USER=root)

3) 根据传入的参数判断是single user模式还是多用户模式然后解析/etc/inittab,因此我们需要构造一个/etc/inittab文件

下面是一个inittab的例子,

::sysinit:/bin/mknod /dev/null c 1 3null::sysinit:/bin/mount -t proc proc /procnull::sysinit:/bin/mount -o remount,rw / # REMOUNT_ROOTFS_RWnull::sysinit:/bin/mkdir -p /dev/ptsnull::sysinit:/bin/mkdir -p /dev/shmnull::sysinit:/bin/mount -anull::sysinit:/bin/hostname -F /etc/hostname# now run any rc scripts::sysinit:/etc/init.d/rcS# Put a getty on the serial porttty0::respawn:/sbin/getty -L tty0 115200 vt100 # GENERIC_SERIAL# Stuff to do for the 3-finger salute::ctrlaltdel:/sbin/reboot# Stuff to do before rebootingnull::shutdown:/etc/init.d/rcKnull::shutdown:/bin/umount -a -rnull::shutdown:/sbin/swapoff -a

先看第一行:
::sysinit:/bin/mknod /dev/null c 1 3

如果没有这行,启动的时候会mount系统目录失败,原因是找不到/dev/null设备,因此我们在第一行加上。

接下来是这一句

null::sysinit:/bin/mount -a

此时系统会执行/etc/fstab,把设备mount到指定目录,因此我们要创建一个/etc/fstab内容如下:

# /etc/fstab: static file system information.## <file system> <mount pt>     <type>   <options>         <dump> <pass>/dev/root       /              ext2     rw,noauto         0      1proc            /proc          proc     defaults          0      0devpts          /dev/pts       devpts   defaults,gid=5,mode=620   0      0tmpfs           /dev/shm       tmpfs    mode=0777         0      0tmpfs           /tmp           tmpfs    defaults          0      0sysfs           /sys           sysfs    defaults          0      0

执行到最后:

::sysinit:/etc/init.d/rcS
之前的工作都是构建系统的基本环境而下面就是个人定制的部分了当然我们要创建这个rcS文件内容如下:

#!/bin/sh# Start all init scripts in /etc/init.d# executing them in numerical order.#for i in /etc/init.d/S??* ;do     # Ignore dangling symlinks (if any).     [ ! -f "$i" ] && continue     case "$i" in        *.sh)            # Source shell script for speed.            (                trap - INT QUIT TSTP                set start                . $i            )            ;;        *)            # No sh extension, so fork subprocess.            $i start            ;;    esacdone/bin/sh

这个脚本的主要目是把/etc/init.d/下面以S也就是启动脚本全部运行一遍,rcK脚本和rcS类似只是一个是启动时运行一个是关闭时运行。

/sbin/init运行后不会自己进入shell,因此你需要在rcS启动脚本全部执行完后进入shell:

/bin/sh

接下来要在/ect/init.d下面创建几个启动脚本:

S10mdev

#!/bin/sh## Start mdev....#case "$1" in  start)        echo "Starting mdev..."        /sbin/mdev -s        ;;  stop)        ;;  restart|reload)        ;;  *)        echo "Usage: $0 {start|stop|restart}"        exit 1esacexit $?

遍历所有设备,并建立设备节点:

       /sbin/mdev -s

S40network

#!/bin/sh## Start the network....#case "$1" in  start)        echo "Starting network..."        /sbin/ifup -a         ;;  stop)        echo -n "Stopping network..."        /sbin/ifdown -a        ;;  restart|reload)        "$0" stop        "$0" start        ;;  *)        echo "Usage: $0 {start|stop|restart}"        exit 1esacexit $?
这里ifup只是将网络端口enable,并没有进行任何配置。如果需要对网络进行配置还需要另外一个工具ifplugd,不是默认选项所以需要在busybox中选中。

执行ifplugd -i eth*

他会首先调用/etc/ifplugd/ifplugd.action的脚本,配置一个默认的ip地址

#!/bin/shif [ "$2" = "up" ]; then  if ! /sbin/ifup $1; then    ifconfig $1 192.168.168.168  fielif [ "$2" = "down" ]; then  /sbin/ifconfig $1 0.0.0.0fiexit 1


接着会调用配置文件/etc/network/interface,这个例子中需要通过dhcp取得ip地址:

auto lo eth0 eth1iface lo inet loopbackiface eth0 inet dhcpiface eth1 inet dhcp

ifplugd会通过调用类似 udhcpc -n -i eth1的命令获取IP地址。


今天就到这里,有空继续



0 0
原创粉丝点击