Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1375501
  • 博文数量: 244
  • 博客积分: 10311
  • 博客等级: 上将
  • 技术积分: 3341
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-14 21:50
文章分类

全部博文(244)

文章存档

2013年(6)

2012年(5)

2011年(16)

2010年(11)

2009年(172)

2008年(34)

分类: LINUX

2008-11-21 09:58:51

初级根文件系统的制作
    本来想把文件系统制作的过程系统的整理一下,发现离最终目的还有一段距离。所以,还是采取边实验边修改,尝试可能情况,最终完成常用的所有功能的移植。这样,在具体应用中只需要做相应的裁减就可以了。为了搞清楚每一个功能部件的依赖关系,要从最小的功能出发,逐步添加功能。
 
    Linux的启动阶段分为两大阶段。第一个阶段从bootloader引导内核,至内核挂载root fs成功为止,这个阶段的一个标志就是如下打印信息:
 

VFS: Mounted root (jffs2 filesystem).
Freeing init memory: 100K

 
    第二个阶段分为如下顺序:init --> getty --> login --> shell四个阶段。而成功的打印信息:
 

[root@listentec ~]#

 
    当然,根据你设定的shell的PS1,显示也会有所不同。但最终成功都会打印出shell prompt。
 
    init现在力求统一标准,最为常用的还是system V init和busybox init。system V init是host上常用的,也是redhat的默认init。system V init是比较复杂的,支持多级别启动。相对于嵌入式系统来说,有些复杂。busybox只支持一个级别,相对来说,更适合嵌入式系统应用。
 
    login在选择上也有busybox login和tinylogin。而tinylogin要支持的好一点。
 
    shell的选择上有busybox ash,也可以交叉编译出一个bash,这样的话bash的功能要强一点。
 
    原来没有细细整理笔记,现在整理时,看到Tekkaman  Ninja已经整理得比较详细了,具体见:http://blog.chinaunix.net/u1/34474/showart_485837.html,现在就参考Tekkaman  Ninja的笔记,再附上自己的理解,算作是根文件系统制作的第一个阶段总结。
 
(1)创建根文件系统的基本目录结构
 
    这个肯定要参考FHS。最初制作的时候,我认为直接用root用户创建就可以了,这个与host还是比较一致的。
 

[armlinux@lqm basicfs1]$ tree -L 1
.
|-- bin
|-- dev
|-- etc
|-- home
|-- lib
|-- mnt
|-- proc
|-- root
|-- rootfs
|-- sbin
|-- sys
|-- tmp
|-- usr
`-- var

 
    也写了小的脚本:
 

[armlinux@lqm fs]$ cat mkrootfs.sh
#!/bin/bash
# make the basic root file system

# set the target documentation
ROOTFS=rootfs
TRUE=1
FALSE=0

# check whether the user is the root
is_root()
{
        if [ `id -u` == 0 ]; then
                return $TRUE
        else
                return $FALSE
        fi
}

# must be the root
if is_root; then
        echo "Must be root to run this script."
        exit 1
fi

# create the rootfs
mkdir $ROOTFS; cd $ROOTFS

mkdir -p bin dev etc lib/modules proc sbin sys usr/bin usr/lib usr/sbin tmp

# create the basic dev
mknod -m 600 dev/console c 5 1
mknod -m 666 dev/null c 1 3

# copy lib
cp -av ../simple_fs/lib

cp -av ../simple_fs/etc/* etc/

 
    这个制作过程并不复杂。只是在最小的组织上还是有待考虑的。
 
(2)编译busybox
    主要就是修改ARCH和CROSS,然后menuconfig,最后指定路径安装。这里有一个版本对应问题,我是选择了cross-3.4.1,编译没有问题。
 
文件: busybox.rar
大小: 0KB
下载: 下载
 
(3)编译tinylogin
 
    这里需要注意的是,不采用tinylogin自带的加密算法。需要改动的地方是:
 

diff -urN tinylogin-1.4.orig/Makefile tinylogin-1.4/Makefile
--- tinylogin-1.4.orig/Makefile 2003-01-03 18:56:33.000000000 +0800
+++ tinylogin-1.4/Makefile 2008-03-19 11:00:01.000000000 +0800
@@ -49,12 +49,12 @@
 # this adds just 1.4k to the binary size (which is a _lot_ less then glibc NSS
 # costs). Note that if you want hostname resolution to work with glibc, you
 # still need the libnss_* libraries.
-USE_SYSTEM_PWD_GRP = true
+USE_SYSTEM_PWD_GRP = false

 # Setting this to `true' will cause tinylogin to directly use the system's
 # shadow password functions. If you leave this off, tinylogin will use its
 # own (probably smaller) shadow password functions.
-USE_SYSTEM_SHADOW = true
+USE_SYSTEM_SHADOW = false

 # This enables compiling with dmalloc ( http:
//dmalloc.com/ )

 # which is an excellent public domain mem leak and malloc problem
@@ -73,7 +73,7 @@

 # If you are running a cross compiler, you may want to set this
 # to something more interesting, like "powerpc-linux-".
-CROSS =
+CROSS = /usr/local/arm/3.4.1/bin/arm-linux-
 CC = $(CROSS)gcc
 AR = $(CROSS)ar
 STRIPTOOL = $(CROSS)strip

 
    这样就可以使用host的/etc/group /etc/passwd /etc/shadow了。
 
(3)/etc/下基本配置文件的探讨
 
    如果你在bootloader的命令行参数中没有指定"init=filename",那么首先init默认执行的是/sbin/init,而该程序现在采用的busybox的init,具体的流程为:
 
    ·为init设置信号处理流程
    ·初始化控制台
    ·剖析inittab文件,/etc/inittab
    ·根据/etc/inittab文件的设置来进行初始化,缺省情况首先执行/etc/init.d/rcS。
    ·执行所有会导致init暂停的inittab命令(动作类型:wait)
    ·执行所有仅执行一次的inittab命令(动作类型:once)
 
    一旦完成,init进程就会循环执行如下工作:
 
    ·执行所有终止时必须重新启动的inittab命令(动作类型:respawn)
    ·执行所有终止时必须重新启动但启动前必须先询问用户的inittab命令(动作类型:askfirst)
 
    其实简单的说,就是找到init,然后读取inittab脚本来执行。如果没有inittab脚本,busybox会按照默认的值进行操作。
 
    这里多说几句的是,no init的错误是很普遍的。主要的原因有:一是没有找到init;二是找了了执行的init,但是没有执行权限,所以还是无法执行;三是找到了init,并且可执行,但是如果是动态编译,对应的共享库有问题的话,也是无法执行程序的。基本的原因就这三个,你当然可以按照最小的文件系统的功能进行测试,只需要一个bin文件(内含sh),一个dev文件夹(内含console),还有一个init脚本,指定exac /bin/sh。测试成功的话,说明你的基本流程可以走通,然后就应该逐步增加功能了。
 
   当然因为后续功能添加的时候,dev中还必须包含null。其他的设备文件则可以通过udev的简化版本mdev来实现了。这个地方需要注意的是mdev对应脚本加载时的初始化顺序是非常重要的,并非随便写。在后面telnet server移植设定的时候就遇到了这个问题。建议读一下mdev.txt,按照上面的流程来写,就没有问题。
 
    ·/etc/inittab  这是init读取的第一个文件,语法是比较晦涩的,功能的易读性上也不好。所以它只是提供了一个动作的入口,具体的功能实现都在执行的操作里。
 

[armlinux@lqm etc]$ cat inittab
::sysinit:/etc/init.d/rcS
::respawn:-/bin/login
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

 
    ·/etc/init.d/rcS
 
    就是shell脚本了,所有的初始化信息都可以逐步加在这里。初步的rcS参考Tekkaman  Ninja的就可以了。这个是我后来完成的一个,仍然是初级脚本。
 

[armlinux@lqm etc]$ cat init.d/rcS
#!/bin/sh
# Initial Environment

# mount /etc/fstab spcified device
/bin/mount -a

# mount devpts in order to use telnetd
/bin/mkdir /dev/pts
/bin/mount -t devpts devpts /dev/pts

# read the busybox docs: mdev.txt
/bin/mount -t sysfs sysfs /sys
/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s

# when mdev is mounted, /sys can be umounted
/bin/umount /sys

# Hostname Setting
/bin/hostname listentec

# Network Setting
/sbin/ifconfig lo 127.0.0.1
/sbin/ifconfig eth0 192.168.1.100 netmask 255.255.255.0
/sbin/route add default gw 192.168.1.1

# Adjust Time
/usr/sbin/ntpdate 210.72.145.44

# NFS client
/bin/mount -o nolock,wsize=1024,rsize=1024 192.168.1.106:/home/armlinux/nfs /mnt/nfs
/bin/echo "NFS client is on now and the mounted point is /mnt/nfs"

# Print the author information
/bin/echo
/bin/echo "********************************"
/bin/echo "         made by lqm            "
/bin/echo "********************************"
/bin/echo

 
    ·/etc/mdev.conf
 
    这个可以为空,也可以根据mdev的配置语法来编写。但是必须要有,否则就会报错。
 
    ·/etc/fstab
 
    这是mount -a要读取的文本。根据需要编写。
 

[armlinux@lqm etc]$ cat fstab
proc /proc proc defaults 0 0
mdev /dev tmpfs defaults 0 0

 
    关于login的还有/etc/passwd, /etc/group, /etc/shadow,直接从host拷贝就可以了。
 

U-Boot 1.3.0 (Mar 18 2008 - 15:25:30)

U-Boot code: 21F00000 -> 21F16EA4 BSS: -> 21F34004
RAM Configuration:
Bank #0: 20000000 32 MB
Flash: 8 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
## Booting image at 21000000 ...
   Image Name: RAM disk
   Image Type: ARM Linux Kernel Image (gzip compressed)
   Data Size: 1149858 Bytes = 1.1 MB
   Load Address: 20008000
   Entry Point: 20008000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK

Starting kernel ...

Linux version 2.6.20 (armlinux@lqm) (gcc version 3.4.1) #1 Tue Mar 18 16:53:40 CST 2008
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0003177
Machine: Jinan ListenTec Co. LTD AT91RM9200DK
Memory policy: ECC disabled, Data cache writeback
Clocks: CPU 179 MHz, master 59 MHz, main 18.432 MHz
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists. Total pages: 8128
Kernel command line: noinitrd root=/dev/mtdblock3 rw rootfstype=jffs2 console=ttySAC0,115200 mem=32M
AT91: 128 gpio irqs in 4 banks
PID hash table entries: 128 (order: 7, 512 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 32MB = 32MB total
Memory: 30012KB available (2108K code, 223K data, 100K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: -1, 2048 bytes)
TCP: Hash tables configured (established 1024 bind 512)
TCP reno registered
NetWinder Floating Point Emulator V0.97 (double precision)
JFFS2 version 2.2. (NAND) (SUMMARY) (C) 2001-2006 Red Hat, Inc.
io scheduler noop registered
io scheduler anticipatory registered (default)
AT91 Watchdog Timer enabled (5 seconds, nowayout)
atmel_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL
atmel_usart.1: ttyS1 at MMIO 0xfffc0000 (irq = 6) is a ATMEL_SERIAL
atmel_usart.2: ttyS2 at MMIO 0xfffc4000 (irq = 7) is a ATMEL_SERIAL
RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize
loop: loaded (max 8 devices)
nbd: registered device at major 43
PPP generic driver version 2.4.2
PPP Deflate Compression module registered
PPP BSD Compression module registered
PPP MPPE Compression module registered
at91_ether: Your bootloader did not configure a MAC address.
eth0: Link now 10-HalfDuplex
eth0: AT91 ethernet at 0xfefbc000 int=24 10-HalfDuplex (36:b9:04:00:24:80)
eth0: Davicom 9161 PHY (Copper)
AT91RM9200-NOR:0x00800000 at 0x10000000
NOR flash on AT91RM9200DK: Found 1 x16 devices at 0x0 in 16-bit bank
 Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
cfi_cmdset_0001: Erase suspend on write enabled
AT91RM9200-NOR:using static partition definition
Creating 5 MTD partitions on "NOR flash on AT91RM9200DK":
0x00000000-0x00020000 : "U-boot"
0x00020000-0x00220000 : "Kernel"
0x00220000-0x00520000 : "RootFS"
0x00520000-0x007e0000 : "Jffs2"
0x007e0000-0x00800000 : "Parameters"
at91_cf: irqs det #64, io #0
mice: PS/2 mouse device common for all mice
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
JFFS2 notice: (1) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.
VFS: Mounted root (jffs2 filesystem).
Freeing init memory: 100K
init started: BusyBox v1.9.1 (2008-03-20 14:53:52 CST)
starting pid 710, tty '': '/etc/init.d/rcS'
eth0: Link now 10-HalfDuplex
22 Mar 08:46:50 ntpdate[722]: step time server 210.72.145.44 offset 1206146805.770447 sec
NFS client is on now and the mounted point is /mnt/nfs

********************************
         made by lqm
********************************

starting pid 732, tty '': '/sbin/telnetd'
starting pid 733, tty '': '/bin/login'

listentec login: root
login[733]: root login on `console

 
    我的引导信息(后来制作的,最初的还没有备份)。

发表于: 2008-03-22,修改于: 2008-03-22 10:27,已浏览2332次,有评论8条 推荐 投诉


网友评论
网友: piaoxiang 时间:2008-03-22 10:32:21 IP地址:122.4.41.★
问题1:平台搭建好之后,可以ping通内网ip和外网ip,但是ping不通域名。
解决办法:
1)增加/etc/resolv.conf
[root@lqm /etc]#cat resolv.conf 
nameserver 192.168.1.1  //加入域名解析器
2)增加相应动态库的支持
增加如下:
libnss_files
libnss_dns
libresolv.so
[root@lqm /lib]#find . -name "libnss*"
./libnss_files.so.2
./libnss_files.so
./libnss_dns-2.3.2.so
./libnss_dns.so
./libnss_files-2.3.2.so
./libnss_dns.so.2
[root@lqm /lib]#find . -name "libresolv*"
./libresolv.so
./libresolv.so.2
./libresolv-2.3.2.so
这样就解决了。效果如下:
[root@lqm ~]#ls
[root@lqm ~]#ping sdu.edu.cn
PING sdu.edu.cn (202.194.15.6): 56 data bytes
64 bytes from 202.194.15.6: seq=0 ttl=58 time=24.994 ms
64 bytes from 202.194.15.6: seq=1 ttl=58 time=24.994 ms
64 bytes from 202.194.15.6: seq=2 ttl=58 time=24.871 ms
--- sdu.edu.cn ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 24.871/24.953/24.994 ms
阅读(1165) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~