zoukankan      html  css  js  c++  java
  • TI Davinci DM6446开发攻略——根文件系统的裁剪和移植 分类: DSP 2013-07-22 16:30 339人阅读 评论(0) 收藏

    一、补充文件系统知识
    Linux根文件系统是存放tool软件、lib文件、script(脚本)、配置文件、其他特殊文件、自己开发的应用程序的地方。嵌入式linux的根文件系统rootfs就像windows操作系统的C、D盘这种概念机制,FLASH对应硬盘。但linux是挂载点的概念,根文件系统是一个整体,组织到一个树状的目录结构中。这种文件组织遵守文件系统科学分类标准FHS,一种国际标准。运行、维护系统所必须的各种
    在开发、测试阶段,基本上都是使用NFS(网络文件系统),NFS文件系统是在你的开发主机HOST里,不是在你的板子里。制作嵌入式产品根文件系统,就是要把NFS指向的文件系统文件夹里所有的内容,通过其他少数几种的Linux文件系统打包生产一个2进制镜像文件,然后以某种方式烧写到FLASH芯片内。开发阶段,特别是应用程序开发、动态加载的驱动模块开发,使用NFS,可以省去麻烦的根文件系统镜像文件的下载和烧写过程,便可以在自己板子上运行这些开发的程序和模块。
     
    Linux支持超过50种文件系统,但是只有少数几种在嵌入式OS中常用,见下图。linux嵌入式产品的根文件系统是需要烧写到Flash芯片里。
     

    Cramfs文件系统:(Compressed ROM File System)是个简单,压缩的,只读的文件系统。除了可以用于MTD下只读并且极少更新img的NOR/NAND,IDE的CF,FTL/NFTL的NOR/NAND,可作为RAM disk的IMG存储。由于简单,Cramfs有一些限制,例如最大支持16M(?256M),没有当前(.)和父(..)目录,页大小固定为4096,gid(8位)最大为255,所有的链接文件计数都是1等等。在cramfs文件系统中,每一页(4KB)被单独压缩,可以随机页访问,其压缩比高达2:1,为嵌入式系统节省大量的Flash存储空间,使系统可通过更低容量的FLASH存储相同的文件,从而降低系统成本。Cramfs文件系统以压缩方式存储,在运行时解压缩,所以不支持应用程序以XIP方式运行,所有的应用程序要求被拷到RAM里去运行,但这并不代表比Ramfs需求的RAM空间要大一点,因为Cramfs是采用分页压缩的方式存放档案,在读取档案时,不会一下子就耗用过多的内存空间,只针对目前实际读取的部分分配内存,尚没有读取的部分不分配内存空间,当我们读取的档案不在内存时,Cramfs文件系统自动计算压缩后的资料所存的位置,再即时解压缩到RAM中。另外,它的速度快,效率高,其只读的特点有利于保护文件系统免受破坏,提高了系统的可靠性。由于以上特性,Cramfs在嵌入式系统中应用广泛。但是它的只读属性同时又是它的一大缺陷,使得用户无法对其内容对进扩充。
    制作Cramfs根文件系统命令如下:
    #mkcramfs [-h] [-e edition] [-i file] [-n name] dirname outfile
    mkcramfs的各个参数解释如下:
     -h:显示帮助信息
    -e edition:设置生成的文件系统中的版本号
    -i file:将一个文件映像插入这个文件系统之中(只能在Linux2.4.0以后的内核版本中使用)
    -n name:设定cramfs文件系统的名字
    dirname:指明需要被压缩的整个目录树
    outfile:最终输出的文件
    cramfsck的命令格式:
    cramfsck [-hv] [-x dir] file
    cramfsck的各个参数解释如下:
    -h:显示帮助信息
    -x dir:释放文件到dir所指出的目录中
    -v:输出信息更加详细
    file:希望测试的目标文件
    例子:#mkcramfs rootfs rootfs.cramfs生成rootfs.cramfs文件系统镜像.其中rootfs是你调试的根文件系统的文件夹,rootfs.cramfs是生产镜像文件的名字。
    Squashfs文件系统:是压缩的只读的fs,保留了Cramfs很多优点,去掉它的限制。压缩比更高。是一个不错的文件系统。命令为:#mksquashfs [source] [dest]
    JFFS2文件系统:可写、保留数据、压缩、掉电保护,提供wear leveling,适合板载NOR、NAND和Doc。JFFS2提供垃圾回收机制,通常可以很好地工作。但是当文件系统接近极限或者要求更新一个非常大的文件,垃圾回收的时间会很长,将会延迟文件系统的操作,这会对没有考虑到这种情况的某些实时要求的软件带来负面的影响。当空间满的时候,尝试更新或者阶段文件内容会被提示文件系统已满并失败,即使看起来不要求添加存储block,这是因为日志结构文件系统,需要在log中增加log。在使用的时候,我们应保证存储空间的充足,上面的应用能够容忍时延(避免快满时候垃圾回收的消耗影响)。 JFFS2用途很广,但是对于现在容量巨大的闪存不适合,新的UBI文件系统出现。JFFS2的不可扩展性是最大的问题,作为JFFS2的升级,JFFS3支持大容量的闪存。JFFS2使用MTD工具:
    #mkfs.jffs2 –r ottfs/ –o images/rootfs-jffs2.img –e 128kiB 其中128是指擦写block的大小,如果超过实际闪存的大小,会引起文件系统的崩溃,如果太小,block内有部分存储空间没能利用。
    #sumtool –i rootfs-jffs2.img –o rootfs-jffs2-summed.img –e 128KiB 增减erase block的summary node。
     
    YAFFS2文件系统:是可写,下电保护的文件系统,广泛引用于Linux和RTOSeS。和JFFS2相比,它减少一些功能,因此速度更快、占用内存资源更少。YAFFS2自带NAND芯片的驱动,是专门为NAND闪存设计的。以前的YAFFS只支持512-BYTE/Page的NAND,而YAFFS2不但兼容512-BYTE/Page,还支持目前流行的2048-BYTE/Page大容量NAND FLASH。YAFFS2文件系统的镜像工具是mkyaffs2img。随便在GOOGLE上输入mkyaffs2img就可以找到满屏幕的制作方法,这里不用介绍。
     
    RAMFS文件系统:
    讨论RAMFS,就不得不讨论RAM disk,在RAM中,而作为一个block设备,内核可以同时支持多个RAM disk。通常用于保存磁盘文件系统中压缩的img。这在嵌入式操作系统的初始化中使用,kernel可以从存储设备中提取initial RAM disk(initrd)img作为的他的根文件系统。一开始,kernel根据boot的参数是否表面intrid,如果是,他将从特定的存贮介质提取文件系统的img并放入RAM disk,同时mount为根文件系统。initrd的机制是以最简单的方式提供一个带根文件系统的内核在RAM中。对于新的系统,推荐使用Initramfs机制。
    Tmpfs文件系统:也是RAM disk的一种,可以使用物理内存,是一个存放在虚拟memory的文件系统,不提供永久保存,适合于存储临时的数据,例如/tmp,用于Linux的page cache和dentry chache。
    RAM disk的特点就是速度快,因为在RAM运行的。缺点就是每次重新启动系统时,前面的工作就无法保存。创建RAM Disk使用的命令式mke2fs。
    有关嵌入式常用的文件系统详细介绍和制作命令、方法,大家可以在网上搜索得到。
     
    二、TI davinci根文件系统target介绍
    在mv_pro_5.0.0/montavista/pro/devkit/arm/v5t_le目录下,有个target的文件夹,这个就是TI EVM的根文件系统了。Target里的内容,见下图,本人是单独COPY出来到自己工作目录下,这点在《开发环境篇》有介绍。TI在这个target文件系统包里放置很多开发工具,其实就是一个开发应用程序的环境,你进到usr目录下就明白这点,里边包括交叉编译命令、很多头文件和应用程序的源代码、usr/lib里的lib文件,等等。其实这些东西肯定是不能全部烧到自己的板子里的。单单这个usr里相关的文件大小就达1G!!!因为TI EVM东西多,复杂,所以我们裁减的时候,最好做好备份。当然,有些朋友是自己手动重新制作根文件系统,再借助“Busybox”这个大名鼎鼎的嵌入式linux瑞士军刀,一个精简的文件系统就出来了。本人在S3C2440、2410的板子上玩过,挺不错的,非常精简。本文暂且不讨论这种方法。
     

    三、TI davinci根文件系统target的裁减
    进入自己工作的target文件夹里,见上图:
    bin文件夹:里边主要是一些linux shell命令,所有用户都可以使用的、基本的命令,都是很基本的东西,暂时不用动它,保留。
    boot文件夹:是存放编译内核的一些相关文件,比如uImage等,这些东西没必要放到板子上的文件系统里,删除掉。
    dev文件夹:存放非常多的设备节点,如果你对这些节点不是很熟悉,分不清哪些是你系统用到的,哪些是不用的,可以保留,整个dev只有16~17k的大小。当然节点太多也不好。
     etc文件夹:存放很多启动的脚本文件、系统配置文件,这是下面移植要讨论的重点。整个文件夹有6~7M,像samba、apt这种在普通嵌入式产品不常用的东西可以删除掉。如果产品不是带LCD图像界面的产品,X11(X Window 系统版本 11,简称 X11,是一个对网络透明的客户/服务器架构的图形显示系统。它支持应用程序在你的屏幕上绘制象素,线条,文字,图象等等。 X11 还包括一些其它的辅助的函数库,使得它可以容易地绘制用户界面,例如:按钮,文本输入区等等)这个可以删除掉,单这个文件夹就有2.85M。
     home文件夹:空的文件夹,系统运行会用到,普通用户的主目录,一定要保留。
     lib文件夹:很多工具和应用程序使用的库文件,不是高高手,最好不要删掉里边的文件。
     media文件夹:空的文件夹,保留。
     mnt文件夹:空文件夹,以后使用U盘和SD卡时,会挂到该目录,所以保留。
     opt文件夹:空文件夹,自己开发的一些应用程序可以放到这里,比如TI evm的一些应用程序就放在/opt/dvsdk/dm6446/,存放encode,decode,encodedecode的应用程序,等等。
     proc文件夹:空的文件夹,系统运行会用到,proc文件系统的挂载点,保留。
     root文件夹:空的文件夹,系统运行会用到,root用户的主目录,一定要保留。
     sbin文件夹:存放很多工具和基本的系统命令,它们用于启动系统、修复系统,在嵌入式产品里,可以把不常用的mkfs.xx的文件全部去掉。其他有很多工具和命令,要根据你自己的产品,不用到的都删掉,裁减sbin建议再单独备份一下sbin,通过NFS,一边删除,一边测试,保证删除掉后你的产品还很好地工作。这是一种笨办法,毕竟要全部理解里边的每个命令和工具的作用也需要很多时间。建议这个文件夹最好不要动太多手脚。
     srv文件夹:空的文件夹,保留。
     sys文件夹:空的文件夹,系统运行会用到,比如sysfs,保留。
     tmp文件夹:空的文件夹,系统运行会用到,存放临时文件,保留。
     usr文件夹:上面提到,这个文件有很多在产品出厂不用到的东西,armv5tl-montavista-linux-gnueabi文件夹直接删除掉;bin文件夹里的arm_v5t_le-XXXXX和armv5tl-montavista-linux-gnueabi-XXX也去掉吧;include、local、share、src、X11R6文件夹全部去掉;Usr/lib/tcng/test干掉;然后根据自己产品的,像perl5、python2.4、X11等等,不用到就搞定它们。笨办法就是使用NFS和板子共同测试,这样下来usr就小多了。
    var文件夹:存放可变的数据,var/cache/cracklib里的文件很大,不知在TI EVM有什么用,本人不用;varlib pm里的文件本人也不用;var/www/html/manual是在开发html的时候用到,本人不用。这几个都是var里耗空间的文件夹。另外,在使用NFS调试的时候,var/log下的文件会保存每次内核启动的打印信息,测试多了,debug,kern.log,messages等文件也加大,所以制作时要注意这些文件的裁减。
        按照上面的动作下来,一个可以用的根文件系统也出来了,但还不是简洁高效的,有些东西还得根据自己的板子要支持的功能选择性保留和裁减。有些工具、命令、应用程序开始没用到,但是后来升级产品会用到,所以,裁减要有针对性和规划性。特别是有些产品使用小于等于64M NAND的嵌入式产品,要做的工作就更多,这里仅供学习和参考。
     
    四、TI davinci根文件系统target的移植
    1、系统的分区:
    在linux-2.6.18移植的博客文章介绍了FLASH的分区,这里就不用重复了,一般分区是: Bootloader(UBL+U-BOOT)+参数 为mtdblock0,kernel为mtdblock1,根文件系统rootfs为mtdblock2。也有这样分的:Bootloader(UBL+U-BOOT) 为mtdblock0,参数为mtdblock1,kernel为mtdblock2,根文件系统为mtdblock3。Bootloader要从FLASH 加载根文件系统,比如jffs2的根文件系统,u-boot的bootargs应该是:mem=118M console=ttyS0,115200n8 rootfstype=jffs2 root=/dev/mtdblock2 noinitrd rw ip=off或者是其他类型的文件系统。同时,u-boot对根文件系统的烧写要支持,因为jffs2,cramfs,yaffs2等每种文件系统的烧写格式都不一样,烧写的地址一定要和内核的FLASH分区地址一一对应。(补充:在DVSDK2.0中,U-BOOT的参数mem=118M,不再是120M,因为TI DVSDK2.0 CODEC ENGINE要求分配给cmem的大小是10M)。
    2、内核选择支持对应的文件系统
       通过make menuconfig的配置界面,你的板子要支持什么样的文件系统,是cramfs,Squashfs,jffs2还yaffs2,则要对对MTD等相关选项进行选择,见linux-2.6.18移植的博客。
       3、对根文件系统权限操作
    Target下每个目录的权限不是全部一样的,根据自己的文件系统的类型,比如yaffs2,tmp、var等目录可以使用chmod –R 777 tmp , chmod –R 777 var命令设置,文件夹域的设置使用chown的命令。为什么要这样强调呢?也许很多人调试DAVINCI 板子会碰到:Starting OpenBSD Secure Shell server: sshd/var/empty/sshd must be owned by root and not group or world-writable. failed (255: ).这个就是根文件系统权限和域得设置有问题。
    4etc目录下的移植
       A、拷贝你的LINUX开发主机etc目录下的passwd、group、shadow文件到etc目录下。这样目标板就使用和你LINUX主机一样的登录账号和密码了。如果passwd、group、shadow被破坏了,如何都进不去板子的shell命令行,而且你的产品没有严重网络安全要求,这里还有一个绝招:把target/etc 下的securetty文件改个名字,不用securetty就可以了,这样输入账号直接回车就可以了。
     
       B、etc目录下新建一个目录sysconfig,并新建文件HOSTNAME,内容为“你公司名字或你喜欢的名字”。同时在etc/init.d/下RcS文件最后面加入:/bin/hostname –F /etc/sysconfig/HOSTNAME,在profile最后面加入:
    USER="`id -un`" (注意 ` 是键盘1旁边的 `
    LOGNAME=$USER
    PS1='[u@h W]# '  (注意 是键盘 ; 旁边的linux文件下显示不一样)
    PATH=$PATH
    HOSTNAME=`/bin/hostname` (注意 ` 是键盘1旁边的 `
    export USER LOGNAME PS1 PATH
    这样在板子上进入shell的命令行时,会显示“[root@你定义的名字~]#”的格式。
     
       C、etc/fstab文件修改:目前这个本人直接使用TI的,但是自己的产品有时会定义
    sysfs              /sys         sysfs       noauto                          0 0
    tmpfs             /dev/shm tmpfs      noauto                                 0 0
    目前没有验证,如果哪个网友对这方面熟悉,可以在博客上讨论。
     
       D、流程介绍
          根文件系统挂接到VFS(linux虚拟文件系统,一种软件接口机制,原理这里不描述)成功后,会根据脚本和配置一步一步运行。我们可以通过以下流程去熟悉:
    先看inittab
          次看init.d/rcS
    然后etc/rc.d/rcS.d,rcS.x等文件,开机是启动/etc/rc.d/rcS.d/下的脚本,然后是/etc/rc.d/rc3.d/下的脚本。只需把用户的程序编译称shell脚本,放在rc3.d下面就可以了。
          S开头的脚本基本上是系统运行初始化要做的工作,K开头就是关机要做的工作。
         客户如果要在开机运行自己的某些应用程序,也可以修改etc/init.d/rcS,在
    for i in /etc/rc.d/rcS.d/S??*
    do
               # Ignore dangling symlinks for now.
               [ ! -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
                         ;;
                esac
    done
    在这后面加自己的运行命令就可以了。
     
       E、制作根文件系统映像文件
          就是使用mkcramfs、mkyaffs2image这些命令对整个修改的target文件进行镜像打包了,格式上面已经介绍了。
     
    五、点评
    以上是本人的经验之谈,肯定有描述不足的地方,希望网友能在博客里指出来,大家一起学习。到目前为止,有关DM6446开发攻略的主架构的文章,基本上接近尾声,最后1篇,有关自己开发的GPIO驱动移植的文章,近期也会出来。以后要写也是某个环节的补充。其实写这些文章,就是希望有这方面的开发高手过来点评一下,指出不足和错误的地方。毕竟本人在这方面还有很多东西要学习。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Android Gradle Plugin指南(五)——Build Variants(构建变种版本号)
    文件内容操作篇clearerr fclose fdopen feof fflush fgetc fgets fileno fopen fputc fputs fread freopen fseek ftell fwrite getc getchar gets
    文件操作篇 close creat dup dup2 fcntl flock fsync lseek mkstemp open read sync write
    嵌入式linux应用程序调试方法
    version control system:git/hg/subversion/cvs/clearcase/vss。software configruation management。代码集成CI:Cruisecontrol/hudson/buildbot
    最值得你所关注的10个C语言开源项目
    如何记录linux终端下的操作日志
    CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
    sizeof, strlen区别
    C/C++嵌入式开发面试题
  • 原文地址:https://www.cnblogs.com/mao0504/p/4706915.html
Copyright © 2011-2022 走看看