嵌入式linux符号表,嵌入式linux大全

本文详细介绍了嵌入式系统中根文件系统的设计方法,包括使用ELDK创建自定义内容、在不同文件系统(如ext2、JFFS2、cramfs、仅读ext2和FAT)上的应用,以及针对CF、SD卡等存储的优化。涵盖了创建过程、文件系统类型选择和启动策略。
摘要由CSDN通过智能技术生成

根文件系统的设计与编译

嵌入式系统的根文件系统(Root File System)设计包括存放的内容、文件系统类型、在哪里存放文件系统和如何启动它。

根文件系统通常存放在目标板的闪存(flash memory)中或CF、SD、MMC卡等中,可以使用像ELDK这样的Linux发布版本创建根文件系统的内容。

下面使用来自ELDK的SELF(Simple Embedded Linux Framework)映像创建根文件系统。

在ELDK软件包中,各种平台构架的SELF映像文件在目录/opt/eldk//images/下,文件名为ramdisk_image.gz,是个压缩的ramdisk映像。

由SELF创建根文件系统tar包的方法列出如下:

//解压缩ramdisk映像

bash$ gzip -d -c -v /opt/eldk/ppc_8xx/images/ramdisk_image.gz >/tmp/ramdisk_image

/opt/eldk/ppc_8xx/images/ramdisk_image.gz: 61.4%

//下面的操作需要root权限

//挂接ramdisk映像

bash# mount -o loop /tmp/ramdisk_image /mnt/tmp

//创建tar包,为了避免需要root权限,这里不包括在tar包中的设备(device)文件

bash# cd /mnt/tmp

bash# tar -zc --exclude='dev/*' -f /tmp/rootfs.tar.gz *

//需要时,为CramFs创建一个单独的tar包,用来包括设备条目

bash# tar -zcf /tmp/devices.tar.gz dev/

bash# cd /tmp

//卸载ramdisk映像

bash# umount /mnt/tmp

(1)根文件系统在ramdisk上

ramdisk常用于存放嵌入式系统的根文件系统,但很少情况将ramdisk映像作为嵌入式系统的根文件系统解决方案。

根文件系统包括在ramdisk中的优点是:编译简单;基于RAM,速度快;Linux内核支持完美;容易使用,甚至可将带有Linux内核的ramdisk放在一个映像文件中;根文件系统是可写的;每次重启动郈的初始状态容易恢复。 缺点是:每次必须将整个文件系统装入RAM,造成启动慢,需要附加存储器存放可写的永久数据。

在ramdisk映像中,根文件系统常用ext2文件系统类型,创建在ramdisk上根文件系统的方法说明如下:通过解开tar包创建目标板根文件系统内容的目录树

$ mkdir rootfs

$ cd rootfs

$ tar zxf /tmp/rootfs.tar.gz使用工具genext2fs创建ramdisk映像,可用设备表文本文件定义在产生的文件系统映像中应创建的设备,这意味着需要root权限。设备表rootfs_devices.tab部分内容列出如表2所示。

表2 设备表文件rootfs_devices.tab部分内容nametypemodeuidgidmajorminorstartinccount

/devd75500-----

/dev/consolec6400051---

/dev/fb0c64000290---

使用工具genext2fs 创建文件系统映像的方法如下:

$ ROOTFS_DIR=rootfs # 根文件系统内容目录

$ ROOTFS_SIZE=3700 # 文件系统映像的大小

$ ROOTFS_FREE=100 # 期望的空闲空间

$ ROOTFS_INODES=380 # 节点(inode)数

$ ROOTFS_DEVICES=rootfs_devices.tab # 设备描述表文件

$ ROOTFS_IMAGE=ramdisk.img # 产生的文件系统映像

$ genext2fs -U \

-d ${ROOTFS_DIR} \

-D ${ROOTFS_DEVICES} \

-b ${ROOTFS_SIZE} \

-r ${ROOTFS_FREE} \

-i ${ROOTFS_INODES} \

${ROOTFS_IMAGE}压缩文件系统映像,方法如下:

$ gzip -v9 ramdisk.img

rootfs.img: 55.6% -- replaced with ramdisk.img.gz创建U-Boot使用的根文件系统映像uRamdisk,方法如下:

$ mkimage -T ramdisk -C gzip -n 'Test Ramdisk Image' \

> -d ramdisk.img.gz uRamdisk

Image Name: Test Ramdisk Image

Created: Sun Jun 12 16:58:06 2005

Image Type: PowerPC Linux RAMDisk Image (gzip compressed)

Data Size: 1618547 Bytes = 1580.61 kB = 1.54 MB

Load Address: 0x00000000

Entry Point: 0x00000000

We now have a root file system image uRamdisk that can be used with U-Boot.

(2)根文件系统在JFFS2文件系统上

在嵌入式系统中,JFFS2作为根文件系统的优点是:文件系统使用压缩,可有效利用闪存空间;它是日志结构的文件系统,对无序的关机是强壮的;它是可写闪存文件系统。缺点是:挂接时间长;由于压缩/解压缩,造成读写操作时间长;垃圾回收线程可在任何时间启动,消耗CPU时间,阻塞对文件系统的访问。

尽管有上面一些不利因素,但基于JFFS2 的根文件系统容易编译,可有效利用可用的资源,并能可靠运行。

创建基于JFFS2的根文件系统的方法如下:通过解开tar包创建目标板根文件系统的内容,方法如下:

$ mkdir rootfs

$ cd rootfs

$ tar zxf /tmp/rootfs.tar.gz使用工具mkfs.jffs2创建一个JFFSW文件系统映像,方法如下:

$ ROOTFS_DIR=rootfs # 根文件系统内容目录

$ ROOTFS_EBSIZE=0x20000 # 闪存的擦除块大小

$ ROOTFS_ENDIAN=b # 目标板系统是大端字节序

$ ROOTFS_DEVICES=rootfs_devices.tab # 设备描述表文件

$ ROOTFS_IMAGE=jffs2.img # 产生的文件系统映像

$ mkfs.jffs2 -U \

-d ${ROOTFS_DIR} \

-D ${ROOTFS_DEVICES} \

-${ROOTFS_ENDIAN} \

-e ${ROOTFS_EBSIZE} \

-o ${ROOTFS_IMAGE}

mkfs.jffs2: skipping device_table entry '/dev': no parent directory!

注意:如果写JFFSW文件系统到NAND flash设备中时,不需要加"-n"或"选项,--no-cleanmarkers",因为不需要清除的标识。

启动内核时,终端显示缺省的分区映射表,列出如下:

0x00000000-0x00040000 : "u-boot"

0x00040000-0x00100000 : "kernel"

0x00100000-0x00200000 : "user"

0x00200000-0x00400000 : "initrd"

0x00400000-0x00600000 : "cramfs"

0x00600000-0x00800000 : "jffs"

0x00400000-0x00800000 : "big_fs"

使用U-Boot装载和存储JFFS2映像到最后一个分区,并建立Linux启动参数,将该映像作为根设备,方法如下:擦除flash

=> era 40400000 407FFFFF

................. done

Erased 35 sectors下载JFFS2映像

=> tftp 100000 /tftpboot/TQM860L/jffs2.img

Using FEC ETHERNET device

TFTP from server 192.168.3.1; our IP address is 192.168.3.80

Filename '/tftpboot/TQM860L/jffs2.img'.

Load address: 0x100000

Loading: #################################################################

done

Bytes transferred = 2033888 (1f08e0 hex)拷贝映像到flash

=> cp.b 100000 40400000 ${filesize}

Copy to Flash... done建立使用flash分区6作为根设备的启动参数

=> setenv mtd_args setenv bootargs root=/dev/mtdblock6 rw rootfstype=jffs2

=> printenv addip

addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${=> setenv flash_mtd 'run mtd_args addip;bootm ${kernel_addr}'

=> run flash_mtd

Using FEC ETHERNET device

TFTP from server 192.168.3.1; our IP address is 192.168.3.80

Filename '/tftpboot/TQM860L/uImage'.

Load address: 0x200000

Loading: #################################################################

done

Bytes transferred = 719233 (af981 hex)

## Booting image at 40040000 ...

(3)根文件系统在cramfs文件系统上

cramfs是压缩的仅读文件系统,作为根文件系统的优点是:文件系统是压缩的,可有效利用闪存空间;允许快速启动,因为仅装载使用的文件,且仅解压缩。缺点是:仅能替换整个映像文件而非单个文件;需要附加的存储空间给可写的永久数据;工具mkcramfs不支持设备表。

创建基于cramfs的根文件系统的方法列出如下:通过解开tar包创建目标板根文件系统的内容,方法如下:

$ mkdir rootfs

$ cd rootfs

$ tar zxf /tmp/rootfs.tar.gz创建需要的设备文件,这里通过解开仅含有设备文件条目的tar包来实现,方法列出如下:

# cd rootfs# tar -zxf /tmp/devices.tar.gz

许多工具需要一些存储地方,这里提供了一个小的可写文件系统。临时文件系统tmpfs是一个选择,为了创建tmpfs文件系统,需要将下面的行加入到脚本/etc/rc.sh中:

# 挂接tmpfs,是因为根文件系统仅读

/bin/mount -t tmpfs -o size=2M tmpfs /tmpfs一些工具需要对某些设备节点有写权限,如:改变属主和权限,可动态创建设备节点,如:/dev/log。这些设备文件需要放在一个可写的文件系统中,仅读的根文件系统用符号链接指向可读设备到新的位置(即在可读写文件系统中的位置),对应符号链接位置部分列出如下:

dev/ptyp0 € /tmpfs/dev/ptyp0 dev/ttyp0 € /tmpfs/dev/ttyp0

dev/ptyp1 € /tmpfs/dev/ptyp1 dev/ttyp1 € /tmpfs/dev/ttyp1

dev/ptyp2 € /tmpfs/dev/ptyp2 dev/ttyp2 € /tmpfs/dev/ttyp2为了放置相应的目录与设备文件在tmpfs文件系统,放置下面的代码在/etc/rc.sh脚本中:

mkdir -p /tmpfs/tmp /tmpfs/dev \

/tmpfs/var/lib/dhcp /tmpfs/var/lock /tmpfs/var/run

while read name minor

do

mknod /tmpfs/dev/ptyp$name c 2 $minor

mknod /tmpfs/dev/ttyp$name c 3 $minor

done <<__eod__>

0 0

1 1

2 2

……

e 14

f 15

__EOD__

chmod 0666 /tmpfs/dev/*使用工具mkcramfs创建cramfs文件系统映像,方法如下:

$ ROOTFS_DIR=rootfs # 带有根文件系统内容的目录

$ ROOTFS_ENDIAN="-r" # 目标板系统有相反的字符序列

$ ROOTFS_IMAGE=cramfs.img # 产生的文件系统映像

PATH=/opt/eldk/usr/bin:$PATH

mkcramfs ${ROOTFS_ENDIAN} ${DEVICES} ${ROOTFS_DIR} ${ROOTFS_IMAGE}

Swapping filesystem endian-ness

bin

dev

etc

...

-48.78% (-86348 bytes) in.ftpd

-46.02% (-16280 bytes) in.telnetd

-45.31% (-74444 bytes) xinetd

Everything: 1864 kilobytes

Super block: 76 bytes

CRC: c166be6d

warning: gids truncated to 8 bits. (This may be a security concern.)可以使用前面JFFS2文件系统的方法建立启动参数,只是将启动参数设置到"rootfstype=cramfs "。

(4)根文件系统在仅读的ext2文件系统上

在闪存上使用标准的ext2文件系统不合适,因为它不含有任何类型的wear leveling,在闪存上的可写文件系统需要有wear leveling保护,需要对无序异常系统关闭有强壮的保护。使用仅读的ext2文件系统将可不需要这些保护。

挂接ext2文件系统时可挂接成仅读的,在某些情况下仅读的ext2文件系统很有用,如:根文件系统在闪存卡上。

仅读ext2文件系统优点是速度快,占用较少的RAM。缺省是由于没有压缩而占用较多的闪存。

与cramfs文件系统作为根文件系统一样,仅读ext2文件系统作为根文件系统,还需要使用tmpfs这样的可写文件系统,存放可写的文件数据。

仅读ext2文件系统作为根文件系统的操作步骤与cramfs文件系统一样,创建方法列出如下:通过解开tar包创建目标板根文件系统的内容,方法如下:

$ mkdir rootfs

$ cd rootfs

$ tar zxf /tmp/rootfs.tar.gz像cramfs根文件系统一样,这里使用tmpfs作为可写的文件系统,并添加下面的行在/etc/rc.sh脚本中:

# 因为根文件系统是仅读,所以挂接tmpfs文件系统作为可写的文件系统

/bin/mount -t tmpfs -o size=2M tmpfs /tmpfs创建设备文件的符号链接放在可写的文件系统中,符号链接从仅读文件系统到可写文件系统,符号链接的目录如下:

dev/ptyp0 € /tmpfs/dev/ptyp0 dev/ttyp0 € /tmpfs/dev/ttyp0

dev/ptyp1 € /tmpfs/dev/ptyp1 dev/ttyp1 € /tmpfs/dev/ttyp1放置相应目录和设备文件在tmpfs文件系统中,将下面的代码放在/etc/rc.sh脚本中:

mkdir -p /tmpfs/tmp /tmpfs/dev \

/tmpfs/var/lib/dhcp /tmpfs/var/lock /tmpfs/var/run

while read name minor

do

mknod /tmpfs/dev/ptyp$name c 2 $minor

mknod /tmpfs/dev/ttyp$name c 3 $minor

done <<__eod__>

0 0

1 1

2 2

3 3

4 4

5 5

6 6

7 7

8 8

9 9

a 10

b 11

c 12

d 13

e 14

f 15

__EOD__

chmod 0666 /tmpfs/dev/*使用genext2fs工具创建ext2文件系统映像,方法如下:

$ ROOTFS_DIR=rootfs # 根文件系统内容的目录

$ ROOTFS_SIZE=3700 # 文件系统映像的大小

$ ROOTFS_FREE=100 # 期望的空闲空间

$ ROOTFS_INODES=380 # 节点号

$ ROOTFS_DEVICES=rootfs_devices.tab # 设备描述文件

$ ROOTFS_IMAGE=ext2.img # 产生的文件系统映像

$ genext2fs -U \

-d ${ROOTFS_DIR} \

-D ${ROOTFS_DEVICES} \

-b ${ROOTFS_SIZE} \

-r ${ROOTFS_FREE} \

-i ${ROOTFS_INODES} \

${ROOTFS_IMAGE}可以使用前面JFFS2文件系统的方法建立启动参数,只是将启动参数设置到"rootfstype=ext2 "。

(5)根文件系统在闪存卡上

可在闪存卡(如:CF、SD、MMC等)上使用仅读ext2文件系统 作为根文件系统,用于启动系统。方法如下:将用工具genext2fs制作的ext2文件系统映像文件ext2.img拷贝到CF卡上,下面列出使用U-Boot拷贝映像文件到CF卡上的方法:

=> tftp 100000 /tftpboot/TQM860L/ext2.img

Using FEC ETHERNET device

TFTP from server 192.168.3.1; our IP address is 192.168.3.80

Filename '/tftpboot/TQM860L/ext2.img'.

Load address: 0x100000

Loading: #################################################################

done

Bytes transferred = 3788800 (39d000 hex)

=> ide part

Partition Map for IDE device 0 -- Partition Type: DOS

Partition Start Sector Num Sectors Type

1 32 500704 6

=> ide write 100000 20 1ce8 #装载地址,第一个分区的起始扇区,扇区数

IDE write: device 0 block # 32, count 7400 ... 7400 blocks written: OK

命令ide write用16进制参数,每个扇区数为512字节,0x20为第一个分区的起始扇区,扇区数计算方法为:3788800/512 = 7400 = 0x1CE8 。设置启动参数,将CF的分区作为仅读根设备,方法如下:

=> setenv cf_args setenv bootargs root=/dev/hda1 ro

=> setenv flash_cf 'run cf_args addip;bootm ${kernel_addr} - ${fdt_addr}'

=> setenv bootcmd run flash_cf

(6)根文件系统在FAT文件系统的一个仅读文件中

在用户嵌入式设备上,用户可使用CF、MMC或SD卡等通用存储介质存储Linux内核和根文件系统。用户可能期望Internet发布软件更新:客户可以从用户的网站下载更新文件,或者将映像文件通过Email发送给客户,客户可将文件拷贝到CF卡上,该CF卡仅有一个FAT或VFAT文件系统,不能直接用作Linux根文件系统,这需要进行一些处理,下面是其中的一种解决方法。

用户的发布软件由两个文件组成,第一个文件是Linux内核带有一个很小的ramdisk映像(U-Boot使用多个文件映像),U-boot能从FAT或VFAT文件系统装载和启动这些映像文件。第二个文件是根文件系统。为了方便和速度,这里使用ext2文件系统作为根文件系统。当Linux启动时,启动刚开始时,它使用附加的ramdisk作为根文件系统。在ramdisk中的程序会以仅读的方式挂接FAT或VFAT文件系统。接着,可使用loop设备将根文件系统与块设备联系起来。最后使用pivot_root切换根文件系统到CF卡上的映像。详细步骤说明如下:用前面制作仅读ext2根文件系统的方法制作ext2.img映像文件。

用前面制作ramdisk映像的方法制作初始ramdisk,需要加入空目录bin、dev、etc、lib、loopfs、mnt、proc和sysroot,加入文件bin/nash(脚本解释器)、linuxrc脚本和从sbin到bin的符号链接,列出如下:

drwxr-xr-x 2 wd users 4096 Apr 13 01:11 bin

-rwxr-xr-x 1 wd users 469512 Apr 11 22:47 bin/nash

drwxr-xr-x 2 wd users 4096 Apr 12 00:04 dev

drwxr-xr-x 2 wd users 4096 Apr 12 00:04 etc

drwxr-xr-x 2 wd users 4096 Apr 12 00:04 lib

-rwxr-xr-x 1 wd users 511 Apr 13 01:28 linuxrc

drwxr-xr-x 2 wd users 4096 Apr 12 00:04 loopfs

drwxr-xr-x 2 wd users 4096 Apr 12 00:09 mnt

drwxr-xr-x 2 wd users 4096 Apr 12 00:04 proc

lrwxrwxrwx 1 wd users 3 Jun 12 18:54 sbin -> bin

drwxr-xr-x 2 wd users 4096 Apr 12 00:04 sysroot还需要用于创建初始ramdisk的小规模设备表,列出如表3。

表3 创建初始ramdisk的小规模设备表nametypemodeuidgidmajorminorstartinccount

/devd75500-----

/dev/consolec6400051---

/dev/hdab6400030---

/dev/hdab6400031118

/dev/loopb6400070014

/dev/nullc6400013---

/dev/ramb6400010012

/dev/ramb6400011---

/dev/ttyc6400040014

/dev/ttyc6400050---

/dev/ttySc64000464014

/dev/zeroc6400015---创建初始ramdisk,方法如下:

$ INITRD_DIR=initrd

$ INITRD_SIZE=490

$ INITRD_FREE=0

$ INITRD_INODES=54

$ INITRD_DEVICES=initrd_devices.tab

$ INITRD_IMAGE=initrd.img

$ genext2fs -U \

-d ${INITRD_DIR} \

-D ${INITRD_DEVICES} \

-b ${INITRD_SIZE} \

-r ${INITRD_FREE} \

-i ${INITRD_INODES} \

${INITRD_IMAGE}

$ gzip -v9 ${INITRD_IMAGE}

结果产生了一个233KB的压缩的ramdisk映像。假定用户已编译了Linux内核映像,现可以用mkimage编译一个U-Boot多文件映像,将Linux内核与初始的ramdisk组合起来,方法如下:

$ LINUX_KERNEL=linuxppc_2_4_devel/arch/ppc/boot/images/vmlinux.gz

$ mkimage -A ppc -O Linux -T multi -C gzip \

> -n 'Linux with Pivot Root Helper' \

> -d ${LINUX_KERNEL}:${INITRD_IMAGE}.gz linux.img

Image Name: Linux with Pivot Root Helper

Created: Mon Jun 13 01:48:11 2005

Image Type: PowerPC Linux Multi-File Image (gzip compressed)

Data Size: 1020665 Bytes = 996.74 kB = 0.97 MB

Load Address: 0x00000000

Entry Point: 0x00000000

Contents:

Image 0: 782219 Bytes = 763 kB = 0 MB

Image 1: 238433 Bytes = 232 kB = 0 MB

新创建的linux.img是必须拷贝到CF卡中的第二个映像文件。linuxrc脚本用于完成根文件系统的设置,其内容列出如下:

#!/bin/nash #用nash脚本解释器解析此文件

echo Mounting /proc filesystem

mount -t proc /proc /proc #挂接/proc文件系统,用于查询一些需要信息

echo Creating block devices

mkdevices /dev #为列在/proc/partitions中的所有分区创建块设备条目

echo Creating root device

mkrootdev /dev/root #为新根文件系统创建块设备

echo 0x0100 > /proc/sys/kernel/real-root-dev

echo Mounting flash card

mount -o noatime -t vfat /dev/hda1 /mnt #挂接CF卡,假定它仅有一个分区在/dev/hda1上

echo losetup for filesystem image

#在CF卡上的根文件系统映像名为rootfs.img,使用用loop设备挂接

losetup /dev/loop0 /mnt/rootfs.img

echo Mounting root filesystem image

mount -o defaults --ro -t ext2 /dev/loop0 /sysroot

echo Running pivot_root

pivot_root /sysroot /sysroot/initrd #将/sysroot作为新的根文件系统

上面的脚本有点小缺陷:由于CF卡挂接在ramdisk中一个目录下,以便能够从根文件系统映像访问。这意味着用户不能卸载(umount)CF卡,阻止用户释放初始ramdisk的空间,将永久失去450kb左右的RAM(用于ramdisk)。首先,在目标板上拷贝2个映像文件到CF卡,方法如下:

bash-2.05b# fdisk -l /dev/hda

Disk /dev/hda: 256 MB, 256376832 bytes

16 heads, 32 sectors/track, 978 cylinders

Units = cylinders of 512 * 512 = 262144 bytes

Device Boot Start End Blocks Id System

/dev/hda1 * 1 978 250352 6 FAT16

bash-2.05b# mkfs.vfat /dev/hda1

mkfs.vfat 2.8 (28 Feb 2001)

bash-2.05b# mount -t vfat /dev/hda1 /mnt

bash-2.05b# cp -v linux.img rootfs.img /mnt/

`linux.img' -> `/mnt/linux.img'

`rootfs.img' -> `/mnt/rootfs.img'

bash-2.05b# ls -l /mnt

total 4700

-rwxr--r-- 1 root root 1020729 Jun 14 05:36 linux.img

-rwxr--r-- 1 root root 3788800 Jun 14 05:36 rootfs.img

bash-2.05b# umount /mnt现准备用U-Boot从CF卡装载uMulti文件(将Linux内核和初始ramdisk组合在一起),并启动它,方法如下:

=> setenv fat_args setenv bootargs rw

=> setenv fat_boot 'run fat_args addip;fatload ide 0:1 200000 linux.img;bootm'

=> setenv bootcmd run fat_boot

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值