Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141878
  • 博文数量: 17
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 295
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-19 16:50
文章存档

2011年(1)

2010年(1)

2008年(15)

我的朋友

分类: LINUX

2008-05-05 11:45:06

我也来做嵌入式 linux(连载三)
2007年05月10日 星期四 下午 04:35
第四章         制作根文件系统
1、建立目录
构建工作空间时,rootfs文件夹用来存放根文件系统,
#cd rootfs
根据根文件系统的基本结构,建立各个对应的目录:
# mkdir dev etc lib proc sbin tmp usr var
# chmod 1777 tmp
# mkdir usr/bin usr/lib usr/sbin
# ls
dev   etc   lib   proc   sbin   tmp   usr   var
# mkdir var/lib var/lock var/log var/run var/tmp
# chmod 1777 var/tmp

准备好根文件系统的骨架后,把前面建立的文件安装到对应的目录中去。

2、拷贝链接库
把uclibc的库文件拷贝到刚才建立的lib文件夹中:
# cd ${PREFIX}/uclibc/lib
[root@skynet lib]# for file in libuClibc ld-uClibc libc libdl \
>; libcrypt libm libresolv libutil
>; do
>; cp $file-*.so ${PRJROOT}/rootfs/lib
>; cp -d $file.so.[*0-9] ${PRJROOT}/rootfs/lib
>; done
cp: cannot stat `libuClibc.so.[*0-9]': No such file or directory
cp: cannot stat `libc-*.so': No such file or directory
有两个文件报找不到,是因为它们本身就不存在,没有关系。
当然,也不必非要全部拷贝,可以根据实际需要来取舍。

4、         拷贝内核映像和内核模块
因为没有模块,所以拷贝模块就省了,
新建boot目录,把刚才建立好的内核拷贝过来
# cd /home/kendo/control-project/daq-module/rootfs/
# mkdir boot
# cd ${PRJROOT}/images
# cp bzImages-2.4.18-rmk5 /home/kendo/control-project/daq-module/rootfs/boot

5、         建立/dev下边的设备文件
在linux中,所有的的设备文件都存放在/dev中,使用mknod命令创建基本的设备文件。
mknod命令需要root权限,不过偶本身就是用的root用户,本来是新建了一个用户专门用于嵌入式制作的,不过后来忘记用了……
# mknod -m 600 mem c 1 1    
# mknod -m 666 null c 1 3
# mknod -m 666 zero c 1 5
# mknod -m 644 random c 1 8
# mknod -m 600 tty0 c 4 0
# mknod -m 600 tty1 c 4 1
# mknod -m 600 ttyS0 c 4 64
# mknod -m 666 tty c 5 0
# mknod -m 600 console c 5 1
基本的设备文件建立好后,再创建必要的符号链接:
# ln -s /proc/self/fd fd
# ln -s fd/0 stdin
# ln -s fd/1 stdout
# ln -s fd/2 stderr
# ls
console   fd   mem   null   random   stderr   stdin   stdout   tty   tty0   tty1   ttyS0   zero

设备文件也可以不用手动创建,听说RedHat /dev下的脚本MAKEDEV 可以实现这一功能,不过没有试过……

基本上差不多了,不过打算用硬盘/CF卡来做存储设备,还需要为它们建立相关文件,因为我的CF在目标机器上是CF-to-IDE,可以把它们等同来对待,先看看Redhat 下边had的相关属性:
# ls -l /dev/hda
brw-rw----     1 root      disk        3,    0 Jan 30   2003 /dev/hda
# ls -l /dev/hda1
brw-rw----     1 root      disk        3,    1 Jan 30   2003 /dev/hda1
对比一下,可以看出,had类型是b,即块设备,主编号为3,次编号从0递增,根限位是
rw-rw----,即660,所以:
# mknod -m 660 hda b 3 0
# mknod -m 660 hda1 b 3 1
# mknod -m 660 hda2 b 3 2
# mknod -m 660 hda3 b 3 3

6、         添加基本的应用程序
未来系统的应用程序,基本上可以分为三类:
1、         基本系统工具,如ls、ifconfig这些……
2、         一些服务程序,管理工具,如WEB、Telnet……
3、         自己开发的应用程序

这里先添加基本的系统工具,有想过把这些工具的代码下载下来交叉编译,不过实在是麻烦,用BusyBox,又精简又好用……
将busybox-1.00.tar.gz下载至sysapps目录下,解压:
#tar zxvf busybox-1.00.tar.gz
#cd busybox-1.00
//进入配置菜单
#make TARGET_ARCH=i386 CROSS=i386-uclibc- PREFIX=${PRJROOT}/rootfs menuconfig
//建立依存关系
#make TARGET_ARCH=i386 CROSS=i386-uclibc- PREFIX=${PRJROOT}/rootfs dep
//编译
#make TARGET_ARCH=i386 CROSS=i386-uclibc- PREFIX=${PRJROOT}/rootfs
这回没有这么好运气了:
/home/kendo/control-project/daq-module/sysapps/busybox-1.00/networking/udhcp/udhcp.a(files.o): In function `read_mac':
files.o(.text+0x4e): undefined reference to `ether_aton'
collect2: ld returned 1 exit status
make: *** [busybox] Error 1
编译udhcp报错了……
重新进入menuconfig,取消udhcp的选项,重新来过,这回一切顺利了。编译完成,安装之:
//安装
#make TARGET_ARCH=i386 CROSS=i386-uclibc- PREFIX=${PRJROOT}/rootfs install
完装完成,回头看看:
# cd bin
# ls
addgroup   busybox   chown   delgroup   echo       kill    ls      mv        ping   rm      sleep
adduser    chgrp     cp      deluser    grep       ln      mkdir   netstat   ps     rmdir   umount
ash        chmod     date    dmesg      hostname   login   mount   pidof     pwd    sh      vi
一下子多了这么多命令……

注意:关于busybox的配置,交叉编译时比较关键的有以下几项:
1、         指明编译器
  • Do you want to build BusyBox with a Cross Compiler?                                       (i386-uclibc-) Cross Compiler prefix  
    2、指明安装路径
    []Don't use /usr
    (${PRJROOT}/rootfs) BusyBox installation prefix  
    其它需要的命令,可以根据实际需要选择


    7、         系统初始化
    内核启动时,最后一个初始化动作就是启动init程序,当然,大多数发行套件的Linux都使用了与System V init相仿的init,可以在网上下载System V init套件,下载下来交叉编译。另外,我也找到一篇写得非常不错的讲解如何编写初始化文件的文件,bsd-init,回头附在后面。不过,对于嵌入式系 统来讲,BusyBox init可能更为合适,在第6步中选择命令的时候,应该把init编译进去。
    #cd ${PRJROOT}/rootfs/etc
    #vi inittab
    我的inittal文件如下:
    #指定初始化文件
    ::sysinit:/etc/init.d/rcS        
    #打开一个串口,波特率为9600                                        
    ::respawn:/sbin/getty 9600 ttyS0
    #启动时执行的shell
    ::respawn:/bin/sh
    #重启时动作
    ::restart:/sbin/init
    #关机时动作,卸载所有文件系统
    ::shutdown:/bin/umount -a –r

    保存退出;

    再来编写rcS脚本:
    #mkdir   ${PRJROOT}/rootfs/etc/init.d
    #cd ${PRJROOT}/rootfs/etc/init.d
    #vi rcS
    我的脚本如下:
    #!/bin/sh

    #Set Path
    PATH=/sbin:/bin
    export PATH

    syslogd -m 60
    klogd

    #install /proc
    mount -n -t proc none /proc

    #reinstall root file system by read/write mode(need: /etc/fstab)
    mount -n -o remount,rw /

    #reinstall /proc
    mount -n -o remount,rw -t proc none /proc

    #set lo ip address
    ifconfig lo 127.0.0.1

    #set eth0 ip address
    #当然,这样子做只是权宜之计,最后做的应该是在这一步引导网络启动脚本,像RedHat
    #那样,自动读取所有指定的配置文件来启动
    ifconfig eth0 192.168.0.68 netmask 255.255.255.0

    #set route
    #同样的,最终这里应该是运行启动路由的脚本,读取路由配置文件
    route add default gw 192.168.0.1

    #还差一个运行服务程序的脚本,哪位有现成的么?
    #网卡/路由/服务这三步,事实上可以合在一步,在rcS这一步中,做一个循环,运行指定启动目录下的所有脚,先将就着这么做吧,确保系统能够正常启动了,再来写这个脚本。

    #set hostname
    hostname MyLinux

    保存退出。

    编写fstab文件
    #vi fstab
    我的fstab很简单:
    /dev/hda1 / ext2 defaults 1 1
    none /proc proc defaults 0 0

    终于差不多了,不过还有一些步骤:
    1、         为多用户做点准备;
    2、         移植至目标系统;
    3、         安装引导程序;
  • 阅读(1024) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~