构建运行在U盘上的LINUX系统
一 背景
在wireless projector项目中需要构建一个图形linux系统,由于嵌入式系统的存储空间太小,所以通过USB口挂接USB存储设备扩展空间,我们的图形LINUX系统将安装在USB存储设备上,并且要负责系统的引导工作。
本文将着重介绍如何构建U盘上的LINUX系统。
二 LINUX USB设备内核支持
Linux USB 驱动程序有三种不同的 USB 主控制器选项,这是因为在主板和 PCI 卡上有三种不同类型的 USB 芯片。\"EHCI\"驱动程序设计成为实现新的高速 USB 2.0 协议的芯片提供支持。\"OHCI\"驱动程序用来为非 PC 系统上的(以及带有 SiS 和 ALi 芯片组的 PC 主板上的)USB 芯片提供支持。\"UHCI\"驱动程序用来为大多数其它 PC 主板(包括 Intel 和 Via)上的 USB 实现提供支持。只需选择与希望启用的 USB 支持的类型对应的\"?HCI\"驱动程序即可。
启用了\"USB support\"和适当的\"?HCI\"USB 主控制器驱动程序后,使 USB 启动并运行只需再进行几个步骤。应该启用\"Preliminary USB device filesystem\",SCSI计算机标准接口,因为通常我们的USB存储设备,模拟为SCSI硬盘而进行访问。
我们生成一个满足上述要求的LINUX内核(内核编译可参照在PC上构造类嵌入式图形LINUX系统一文中相关介绍)。
注:主板必须要支持USB启动,在主板中U盘启动应选择usb-zip,USB移动硬盘启动应选择usb-hdd,USB CDROM启动应选择usb-cdrom。
三 USB设备启动问题
由于优盘的初始化过程比执行/sbin/init慢,导致内核已经启动完成了,优盘还没有完成初始化工作,因此根文件系统没有加载,这时执行/sbin/init命令肯定不成功。
解决方法:
1. 通过建立initrd.img文件,在启动内核时加载initrd.img文件到内存中,等待3 秒使优盘完成初始化工作,再执行/sbin/init指令。
1、 建立initrd.img文件
# mkdir -p /mnt/initrd
# cd /tmp
# mkinitrd /tmp/initrd.gz 2.4.20
(mkinitrd这个命令是用来产生initrd.img文件的,在系统/lib/modules中有不同系统内核版本的文件目录,比如2.4.20这个内核的目录,mkinitrd这个命令就是产生/lib/modules下对应的内核版本的initrd.img文件,她的最后一个参数就是内核的版本号如2.4.20)
2、解压initrd.img文件,修改启动脚本linuxrc
# gunzip initrd.gz
# mount -o loop /tmp/initrd /mnt/initrd
# cp /sbin/busybox /mnt/initrd/bin
# cd /mnt/initrd/bin
# ln -s busybox sleep
# vi /mnt/initrd/linuxrc
加入如下内容:
echo 'wait 3 seconds.....'
/bin/sleep 3
3、重新生成initrd.img文件
由于缺省建立的initrd文件比较大(为4MB),为了加快优盘的启动,必须减小它。具体操作如下:
# mkdir -p /mnt/initrdusb
# cd /tmp
# dd if =/dev/zero of= /tmp/initrdusb bs=1M count=1
# mke2fs -m0 initrdusb
# mount -o loop /tmp/initrdusb /mnt/initrdusb
# cp -a /mnt/initrd/* /mnt/initrdusb
# umount /mnt/initrd
# umount /mnt/initrdusb
# cd /tmp
# gzip -9 initrdusb
# cp initrdusb.gz /boot/initrd.img
2. 修改内核初始化代码
/init/do_mounts.c
……
* Allow the user to distinguish between failed open
* and bad superblock on root device.
*/
- printk (\"VFS: Cannot open root device \"%s\" or %s\",
+ printk (\"VFS: Cannot open root device \"%s\" or %s,
retrying in 1 second.\", root_device_name, kdevname (ROOT_DEV));
- printk (\"Please append a correct \"root=\" boot option\");
- panic(\"VFS: Unable to mount root fs on %s\",
- kdevname(ROOT_DEV));
+ printk (\"You may need to append a correct \"root=\" boot option\");
+ printk (\"or wait for the root device to become ready.\");
+
+ /* wait 1 second and try again,
+ * allowing time for hubs/devices to become ready */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ goto retry;
}
panic(\"VFS: Unable to mount root fs on %s\", kdevname(ROOT_DEV));
out:
……
(减号是要删掉的代码,加号是要添加的代码)
四 建立U盘文件系统
1、 格式化U盘为ext2文件系统
Fdisk /dev/sda
D 删掉原U盘上的分区
N 重新建一个新的分区
P 建立主分区(大小就整个U盘的大小)
W 退出并保存新分区表
Mkfs.ext2 –m0 /dev/sda1
(U盘被当成SCSI硬盘使用,所以设备号是sda, sda1表示是设备sda上的第一个分区,我们U盘上就分了一个区,所以就是指整个U盘了)
2、 建立文件结构
Mkdir /mnt/usb
Mount /dev/sda1 /mnt/usb
Cd /mnt/usb
Mkdir boot
将编译好的内核与initrd.img文件拷贝到boot目录 ,将/boot/grub目录中的stage1、stage2文件也拷到boot目录中。
Vi grub.conf 建立grub配置文件
title USB-LINUX
root (hd0,0)
kernel /boot/vmlinuz-2.4.20-usb ro root=/dev/sda1
initrd /boot/initrd.img
(注:hd0表示第一块硬盘,即要把其它硬盘都拔掉,指留下U盘)
安装grub
Grub
grub> root (hd0,0)
grub> setup (hd0)
grub>quit
退出,就可了。
Mkdir bin
Mkdir sbin
将busybox生成的bin sbin目录的文件拷到bin sbin中去,并将busybox中的linuxrc文件拷到U盘上(busybox相关资料可以参考在PC上构造类嵌入式图形LINUX系统一文中相关介绍)。
Mkdir dev
建立loop1 loop2 loop3 loop4 loop5
console zero null pts ptmx
tty0 tty1 tty2 tty3 tty4 tty5 tty6 tty7
fb fb0 fb1 fb2 fb3 fb4 fb5
ram0 ram1 ram2 ram3
sda sda1 sda2 sdb sdb1 sdb2 sdb3
hda hda1 hda2 hdb hdb1 hdb2 hdb3 设备文件
其中,fd0,hda,ram,ram1,tty1,null,zero,loop1,fb0,fb等是必备的.
Mkdir etc
建立etc目录下的配置文件
busybox.conf
group
inittab
motd
passwd
resolv.conf
shadow
fstab
init.d
issue
mtab
profile
其中init.d是一个目录,从busybox源代码目录下拷贝过来.
busybox.conf 空文件.
fstab
/dev/sda1 / ext2 defaults 0 0
none /proc proc defaults 0 0
group
root:x:0:root
inittab
::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
tty2::respawn:/sbin/getty 38400 tty2
tty3::respawn:/sbin/getty 38400 tty3
tty4::respawn:/sbin/getty 38400 tty4
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
issue
like embed linux system 0.1
motd 空文件
mtab 空文件
passwd
root::0:0:root:/root:/bin/ash
profile
# /etc/profile: system-wide .profile file for the Bourne shells
echo
echo
export PS1=\"[u@h w]$\"
echo \"Done\"
alias ll='ls -l'
alias du='du -h'
alias df='df -h'
alias rm='rm -i'
echo
resolv.conf
nameserver 192.168.15.20
shadow (这个文件可以从原系统上拷过来)
root:$1$$adltAB9Sr/MSKqylIvSJT/:12705:0:99999:7:::
其中有很多是从原系统的/etc下拷贝过来修改的,当然,你也可以根据自己的需要修改这些文件.其中最重要的是fstab和inittab,busybox内建的init程序用到的inittab文件的语法和一般的不一样,不能直接把原系统/etc下inittab文件拷贝过来.可以把busybox-1.00目录下的示例文件拷贝过来修改用.具体请看busybox的文档.busybox的init也可以不用inittab.
init.d下的文件:
rcS
请确保这个文件是可执行的,否则请改成可执行的:
#chmod u+x rcS
rcS的内容:
#! /bin/sh
PATH=/sbin:/bin
export PATH
mount -n -t proc none /proc
umount /initrd
mount -n -o remount,rw /
mount -n -o remount,rw -t proc none /proc
mkdir proc etc lib usr tmp var initrd root
将/lib/modules/中内核对应模块文件拷贝到lib目录中去。
到此整个系统就制作完成了,我们可以将我们的应用添加上去来满足自己的应用需求。
孙斌 RD8