根文件系统树的制作及详解

2019-07-13 01:59发布


制作的文件系统用于的平台:fl2440(ARM9)

一、嵌入式Linux文件系统简介

1、基本概念:

  linux支持多种文件系统,包括ext2、ext3、vfat、ntfs、iso9660、jffs、romfs和nfs等,为了对各类文件系统 进行统一管理,Linux引入了虚拟文件系统VFS(Virtual File System),为各类文件系统提供一个统一的操作界面和应用编程接口。Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。之后可以自动或手动挂载其他的文件系统。因此,一个系统中可以同时存在不同的文件系统。
  不同的文件系统类型有不同的特点,因而根据存储设备的硬件特性、系统需求等有不同的应用场合。在嵌入式Linux应用中,主要的存储设备为 RAM(DRAM, SDRAM)和ROM(常采用FLASH存储器),常用的基于存储设备的文件系统类型包括:jffs2, yaffs, cramfs, romfs, ramdisk, ramfs/tmpfs等.
这里写图片描述

2、常见文件系统:

(1)initramfs
   initramfs在编译内核的同时被编译并与内核生成一个映像文件,可以压缩也可以不压缩,但是目前只支持cpio包格式。它是根文件系统制作和制作的一种非常简单的方法,也可以通过执行这个文件系统中的程序引导真正的文件系统,这样加载根文件系统的工作就不是内核的工作,而是initramfs的工作。由于initramfs使用cpio包格式,所以很容易将一个单一的文件、目录、node编译链接到系统中去,这样很简单的系统中使用起来很方便,不需要另外挂接文件系统。
但是因为cpio包实际是文件、目录、节点的描述语言包,为了描述一个文件、目录、节点,要增加很多额外的描述文字开销,特别是对于目录和节点,本身很小额外添加的描述文字却很多,这样使得cpio包比相应的image文件大很多。 (2)Ramdisk
  ramdisk是一种基于内存的虚拟文件系统(并非一个实际的文件系统),它将一部分固定大小(这个大小在编译内核的make menuconfig时配置)的内存当作硬盘一个分区来使用。ramdisk是一种将实际的文件系统装入内存的机制,并且可以作为根文件系统,通常我们会使用ext2或ext3文件系统来格式化它。由于ramdisk是在内存中进行操作的,所以我们可以对里面的文件进行添加,修改,删除等等操作,但是一掉电,就什么也没有了。由于这个特性,我们可以将一些经常被访问而又不会更改的文件(如只读的根文件系统)通过Ramdisk放在内存中,这样可以明显地提高系统的性能。
  在Linux的启动阶段,内核和ramdisk都是由 bootloader在启动时加载至内存的指定位置(),而initrd提供了一套机制,可以将内核映像和根文件系统一起载入内存。initrd 是boot loader initialized RAM disk,顾名思义是在系统初始化引导时候用的ramdisk,它的作用是完善内核的模块机制,让内核的初始化流程更具弹性。  (3) ramfs/tmpfs
Ramfs是Linus Torvalds开发的一种基于内存的文件系统,工作于虚拟文件系统(VFS)层,不能格式化,可以创建多个,在创建时可以指定其最大能使用的内存大小。(实际上,VFS本质上可看成一种内存文件系统,它统一了文件在内核中的表示方式,并对磁盘文件系统进行缓冲。)Ramfs/tmpfs文件系统把所有的文件都放在RAM中,所以读/写操作发生在RAM中,可以用ramfs/tmpfs来存储一些临时性或经常要修改的数据,例如/tmp和/var目录,这样既避免了对Flash存储器的读写损耗,也提高了数据读写速度。Ramfs/tmpfs相对于传统的Ramdisk的不同之处主要在于:不能格式化,文件系统大小可随所含文件内容大小变化。但他们都不可以像ramdisk一样作为根文件系统,而只能想procfs,devfs一样作为伪文件系统使用。 (4)NFS
  NFS网络文件系统(Network File System)是由Sun开发并发展起来的一项在不同机器、不同操作系统之间通过网络共享文件的技术。在嵌入式Linux系统的开发调试阶段,可以利用该技术在主机上建立基于NFS的根文件系统,挂载到嵌入式设备,可以很方便地修改根文件系统的内容。
  
(5) 伪文件系统
  以上讨论的都是基于存储设备的文件系统(memory-based file system),它们都可用作Linux的根文件系统(除tmpfs和ramfs外)。实际上,Linux还支持逻辑的或伪文件系统(logical or pseudo file system),例如procfs(proc文件系统),用于获取系统信息,以及devfs(设备文件系统)和sysfs,用于维护设备文件。

基于FLASH的文件系统:

  Flash(闪存)作为嵌入式系统的主要存储媒介,有其自身的特性。Flash的写入操作只能把对应位置的1修改为0,而不能把0修改为1(擦除Flash就是把对应存储块的内容恢复为1),因此,一般情况下,向Flash写入内容时,需要先擦除对应的存储区间,这种擦除是以块(block)为 单位进行的。
  闪存主要有NOR和NAND两种技术(简单比较见附录)。Flash存储器的擦写次数是有限的,NAND闪存还有特殊的硬件接口和读写时序。因 此,必须针对Flash的硬件特性设计符合应用要求的文件系统;传统的文件系统如ext2等,用作Flash的文件系统会有诸多弊端。
  在嵌入式Linux下,MTD(Memory Technology Device,存储技术设备)为底层硬件(闪存)和上层(文件系统)之间提供一个统一的抽象接口,即Flash的文件系统都是基于MTD驱动层的(参见下面的Linux下的文件系统结构图)。使用MTD驱动程序的主要优点在于,它是专门针对各种非易失性存储器(以闪存为主)而设计的,因而它对Flash有 更好的支持、管理和基于扇区的擦除、读/写操作接口。
顺便一提,一块Flash芯片可以被划分为多个分区,各分区可以采用不同的文件系统;两块Flash芯片也可以合并为一个分区使用,采用一个文件系统。即文件系统是针对于存储器分区而言的,而非存储芯片。 1、 jffs2
  JFFS文件系统最早是由瑞典Axis Communications公司基于Linux2.0的内核为嵌入式系统开发的文件系统。JFFS2(Journalling Flash FileSystem v2,日志闪存文件系统版本2 )是RedHat公司基于JFFS开发的闪存文件系统,最初是针对RedHat公司的嵌入式产品eCos开发的嵌入式文件系统,所JFFS2也可以用在Linux, uCLinux中。它主要用于NOR型闪存,基于MTD驱动层,特点是:可读写的、支持数据压缩的、基于哈希表的日志型文件系统,并提供了崩溃/掉电安全保护,提供“写平衡”支持等。缺点主要是当文件系统已满或接近满时,因为垃圾收集的关系而使jffs2的运行速度大大放慢。
  Jffs2不适合用于NAND闪存主要是因为NAND闪存的容量一般较大,这样导致jffs2为维护日志节点所占用的内存空间迅速增大,另外,jffs2文件系统在挂载时需要扫描整个FLASH的内容,以找出所有的日志节点,建立文件结构,对于大容量的NAND闪存会耗费大量时间。
  目前jffs3正在开发中,关于jffs2系列文件系统的使用详细文档,可参考MTD补丁包中mtd-jffs-HOWTO.txt。 2、 yaffs
  yaffs/yaffs2(Yet Another Flash File System)是专为嵌入式系统使用NAND型闪存而设计的一种日志型文件系统。与jffs2相比,它减少了一些功能(例如不支持数 据压缩),所以速度更快,挂载时间很短,对内存的占用较小。另外,它还是跨平台的文件系统,除了Linux和eCos,还支持WinCE, pSOS和ThreadX等。
  yaffs/yaffs2自带NAND芯片的驱动,并且为嵌入式系统提供了直接访问文件系统的API,用户可以不使用Linux中的MTD与VFS,直接对文件系统操作。当然,yaffs也可与MTD驱动程序配合使用。yaffs与yaffs2的主要区别在于,前者仅支持小页(512 Bytes) NAND闪存,后者则可支持大页(2KB) NAND闪存。同时,yaffs2在内存空间占用、垃圾回收速度、读/写速度等方面均有大幅提升。 3、 ubifs
  无排序区块图像文件系统(Unsorted Block Image File System, UBIFS)是用于固态硬盘存储设备上,并与LogFS相互竞争,作为JFFS2的后继文件系统之一。真正开始开发于2007年,并于2008年10月第一次加入稳定版本于Linux核心2.6.27版。UBIFS最早在2006年由IBM与Nokia的工程师Thomas Gleixner,Artem Bityutskiy所设计,专门为了解决MTD(Memory Technology Device)设备所遇到的瓶颈。由于Nand Flash容量的暴涨,YAFFS等皆无法再去控制Nand Flash的空间。UBIFS通过子系统UBI处理与MTD device之间的动作。与JFFS2一样,UBIFS 建构于MTD device 之上,因而与一般的block device不兼容。
  JFFS2运行在MTD设备之上,而UBIFS则只能工作于UBI volume之上。也可以说,UBIFS涉及了三个子系统:
1. MTD 子系统, 提供对flash芯片的访问接口, MTD子系统提供了MTD device的概念,比如/dev/mtdx,MTD可以认为是raw flash
2. UBI subsystem,为flash device提供了wear-leveling和 volume management功能; UBI工作在MTD设备之上,提供了UBI volume;UBI是MTD设备的高层次表示,对上层屏蔽了一些MTD不得不处理的问题,比如wearing以及坏块管理
3. UBIFS文件系统,工作于UBI之上 以下是UBIFS的一些特点:
Ø 可扩展性:UBIFS对flash 尺寸有着很好的扩展性; 也就是说mount时间,内存消耗以及I/O速度都不依赖与flash 尺寸(对于内存消耗并不是完全准确的,但是依赖性非常的低); UBIFS可以很好的适应GB flashes; 当然UBI本身还有扩展性的问题,无论如何 UBI/UBIFS都比JFFS2的可扩展性好,此外如果UBI成为瓶颈,还可以通过升级UBI而不需改变UBIFS
Ø 快速mount:不像JFFS2,UBIFS在mount阶段不需要扫描整个文件系统,UBIFS mount介质的时间只是毫秒级,时间不依赖与flash的尺寸;然而UBI的初始化时间是依赖flash的尺寸的,因此必须把这个时间考虑在内
Ø write-back 支持: 回写或者叫延迟写更准确些吧,同JFFS2的write-through(立即写入内存)相比可以显著的提高文件系统的吞吐量。
Ø 异常unmount适应度:UBIFS是一个日志文件系统可以容忍突然掉电以及unclean重启; UBIFS 通过replay 日志来恢复unclean unmount,在这种情况下replay会消耗一些时间,因此mount时间会稍微增加,但是replay过程并不会扫描整个flash介质,所以UBIFS的mount时间大概在几分之一秒。
Ø 快速I/O - 即使我们disable write-back(可以在unmount时使用-o sync mount选项), UBIFS的性能仍然接近JFFS2; 记住,JFFS2的同步I/O是非常惊人的,因为JFFS2不需要在flash上维护indexing data结构, 所以就没有因此而带来的负担; 而UBIFS恰恰是有index数据的。 UBIFS之所以够快是因为UBIFS提交日志的方式:不是把数据从一个地方移动到另外一个位置,而只是把数据的地址加到文件系统的index,然后选择不同的eraseblock作为新的日志块,此外还有multi-headed日志方式等技巧。
Ø on-the_flight compression - 存储在flash介质上的数据是压缩的;同时也可以灵活的针对单个文件来打开关闭压缩; 例如,可能需要针对某个特定的文件打开压缩,或者可能缺省方式下支持压缩,但是对多媒体文件则关闭压缩。
Ø 可恢复性 - UBIFS可以从index破坏后恢复; UBIFS中的每一片信息都有一个header来描述,因此可以通过扫描这个flash介质来重构文件系统,这点和JFFS2非常类似;想像一下,如果你擦出了FAT文件系统的FAT表,那么对于FAT FS是致命的错误,但是如果擦除UBIFS的index,你人然可以重构文件系统,当然这需要一个特定的用户空间程序来做这个恢复
Ø 完整性 - UBIFS通过写checksum到flash 介质上来保证数据的完整性,UBIFS不会无视损坏文件数据或meta-data; 缺省的情况,UBIFS仅仅检查meta-data的CRC,但是你可以通过mount选项,强制进行data CRC的检查 4、 Cramfs
  Cramfs(Compressed ROM File System)是Linux的创始人 Linus Torvalds参与开发的一种只读的压缩文件系统,它也基于MTD驱动程序。在cramfs文件系统中,每一页(4KB)被单独压缩,可以随机页访问,其压缩比高达2:1,为嵌入式系统节省大量的Flash存储空间,使系统可通过更低容量的FLASH存储相同的文件,从而降低系统成本。
Cramfs文件系统以压缩方式存储,在运行时解压缩,所以不支持应用程序以XIP方式运行,所有的应用程序要求被拷到RAM里去运行,但这并不代表比Ramfs需求的RAM空间要大一点,因为Cramfs是采用分页压缩的方式存放档案,在读取档案时,不会一下子就耗用过多的内存空间,只针对目前实际读取的部分分配内存,尚没有读取的部分不分配内存空间,当我们读取的档案不在内存时,Cramfs文件系统自动计算压缩后的资料所存的位置,再即时 解压缩到RAM中。
另外,它的速度快,效率高,其只读的特点有利于保护文件系统免受破坏,提高了系统的可靠性。Cramfs映像通常是放在Flash中,但是也能放在别的文件系统里,使用loopback设备可以把它安装别的文件系统里。
由于以上特性,Cramfs在嵌入式系统中应用广泛。但是它的只读属性同时又是它的一大缺陷,使得用户无法对其内容对进扩充。 5、 Romfs
  传统型的Romfs文件系统是一种简单的、紧凑的、只读的文件系统,不支持动态擦写保存,按顺序存放数据,因而支持应用程序以 XIP(eXecute In Place,片内运行)方式运行,在系统运行时,节省RAM空间。uClinux系统通常采用Romfs文件系统。 6、 其他文件系统
fat/fat32也可用于实际嵌入式系统的扩展存储器(例如PDA, Smartphone, 数码相机等的SD卡),这主要是为了更好的与最流行的Windows桌面操作系统相兼容。ext2也可以作为嵌入式Linux的文件系统,不过将它用于FLASH闪存会有诸多弊端。

二、创建目录

[root@Centoros rootfs]# mkdir -p
{apps,bin,data,dev,info,proc,root,sbin,sys,tmp,var,etc/{,init.d,dropbear},mnt/{,usb,sdc,nfs,dev},usr/{,bin,sbin,lib,share},lib/{,modules/{,3.0.54}}}

`[root@Centoros rootfs]# tree -L 3 ├── apps #挂载Application所在分区用的目录 ├── bin ├── data ├── dev ├── etc │?? ├── dropbear #dropbear ssh server依赖的文件 │?? └── init.d #系统启动初始化脚本 ├── info ├── lib │?? └── modules #insmod时,依赖/lib/modules/内核版本目录 │?? └── 3.0.54 ├── mnt #设备在运行时的一些挂载点 │?? ├── dev │?? ├── nfs │?? ├── sdc │?? └── usb ├── proc ├── root ├── sbin ├── sys ├── tmp ├── usr │?? ├── bin │?? ├── lib #用户程序动态库放到这里 │?? ├── sbin │?? └── share └── var

三、Dev目录下创建设备文件

因为内核挂载完文件系统后,init进程需要用到/dev/console和/dev/null这两个设备文件来调用mdev构建dev,所以必须在制作文件系统时静态创建这两个设备文件,否则在系统启动时将提示
Waring:unable to open an initial console:
mknod [options] name {bc} major minor -m表示权限 major:主设备号 minor:次设备 [yangni@Certoros rootfs]$ sudo mknod -m666 dev/null c 1 3 [yangni@Certoros rootfs]$ sudo mknod -m666 dev/console c 5 1 [yangni@Certoros rootfs]$ sudo mknod -m666 dev/ttyS0 c 4 64 [yangni@Certoros rootfs]$ sudo mknod -m666 dev/ttySAC0 c 4 64 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock0 b 31 0 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock1 b 31 1 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock2 b 31 2 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock3 b 31 3 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock4 b 31 4 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock5 b 31 5 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock6 b 31 6 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock7 b 31 7 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock8 b 31 8 [yangni@Certoros rootfs]$ sudo mknod dev/mtdblock9 b 31 9 [yangni@Certoros rootfs]$ ls -l dev/ total 0 crw-rw-rw- 1 root root 5, 1 Apr 25 20:43 console brw-r--r-- 1 root root 31, 0 Apr 25 20:49 mtdblock0 brw-r--r-- 1 root root 31, 1 Apr 25 20:49 mtdblock1 brw-r--r-- 1 root root 31, 2 Apr 25 20:49 mtdblock2 brw-r--r-- 1 root root 31, 3 Apr 25 20:49 mtdblock3 brw-r--r-- 1 root root 31, 4 Apr 25 20:49 mtdblock4 brw-r--r-- 1 root root 31, 5 Apr 25 20:49 mtdblock5 brw-r--r-- 1 root root 31, 6 Apr 25 20:50 mtdblock6 brw-r--r-- 1 root root 31, 7 Apr 25 20:50 mtdblock7 brw-r--r-- 1 root root 31, 8 Apr 25 20:51 mtdblock8 brw-r--r-- 1 root root 31, 9 Apr 25 20:51 mtdblock9 crw-rw-rw- 1 root root 1, 3 Apr 25 20:43 null crw-rw-rw- 1 root root 4, 64 Apr 25 20:44 ttyS0 crw-rw-rw- 1 root root 4, 64 Apr 25 20:44 ttySAC0

四、 Var 目录下创建符号链接文件

[yanngi@Certoros rootfs]$ ln -s /tmp var/lock [yanngi@Certoros rootfs]$ ln -s /tmp var/log [yanngi@Certoros rootfs]$ ln -s /tmp var/run [yanngi@Certoros rootfs]$ ln -s /tmp var/tmp [yanngi@Certoros rootfs]$ ls -l var/ total 0 lrwxrwxrwx 1 yangni trainning 4 Apr 25 20:57 lock -> /tmp lrwxrwxrwx 1 yangni trainning 4 Apr 25 20:57 log -> /tmp lrwxrwxrwx 1 yangni trainning 4 Apr 25 20:57 run -> /tmp lrwxrwxrwx 1 yangni trainning 4 Apr 25 20:57 tmp -> /tmp

五、拷贝交叉编译器中的动态库到相应的目录下

[yanngi@Certoros rootfs]$cp -af /opt/buildroot-2012.08/arm920t/usr/arm-unknown-linux-uclibcgnueabi/sysroot/lib/*so* lib/ [yanngi@Certoros rootfs]$cp -af /opt/buildroot-2012.08/arm920t/usr/arm-unknown-linux-uclibcgnueabi/lib/*so* lib/ 上诉步骤可以用一个安全脚本来完成: #!/bin/bash if [ $# != 1 ] ; then echo "Usage: $0 [rootfs_path]" exit; fi INST_PATH=$1 if [ ! -d $INST_PATH -o $INST_PATH == "/" ] ; then echo "$INST_PATH is not exist or it's root path,exit now" exit; fi if [ ! -d $INST_PATH/data ] ; then echo "It's not an embedded root file system tree" exit; fi CROSSTOOL_PATH=/opt/buildroot-2012.08/arm920t/usr/ CMD_PREFIX=sudo set -ev LIB_PATH=$INST_PATH/lib USR_LIB_PATH=$INST_PATH/usr/lib $CMD_PREFIX rm -rf $LIB_PATH/*.so* $CMD_PREFIX rm -rf $USR_LIB_PATH/* $CMD_PREFIX cp -af $CROSSTOOL_PATH/arm-unknown-linux-uclibcgnueabi/sysroot/lib/*.so* $LIB_PATH $CMD_PREFIX cp -af $CROSSTOOL_PATH/arm-unknown-linux-uclibcgnueabi/lib/*.so* $LIB_PATH $CMD_PREFIX cp -af $CROSSTOOL_PATH/lib/*.so* $LIB_PATH #$CMD_PREFIX sudo rm -rf $LIB_PATH/libmudflap* $CMD_PREFIX sudo rm -rf $LIB_PATH/libstdc++.so.6.0.14-gdb.py mkdir -p lib $CMD_PREFIX cp -af $CROSSTOOL_PATH/arm-unknown-linux-uclibcgnueabi/sysroot/usr/lib/*.so* lib #$CMD_PREFIX cp -af $CROSSTOOL_PATH/arm-unknown-linux-uclibcgnueabi/sysroot/usr/lib/engines lib $CMD_PREFIX sudo rm -rf lib/libstdc++.so* $CMD_PREFIX mv lib/* $USR_LIB_PATH rm -rf lib

六、etc目录下相关操作

1、创建/etc/inittab文件

  inittab为linux初始化文件系统时init初始化程序用到的配置文件。这个文件负责设置init初始化程序初始化脚本在哪里;每个运行级初始化时运行的命令; 开机、关机、重启对应的命令;各运行级登陆时所运行的命令。 [yangni@Certoros rootfs]$ cd etc/
[yangni@Certoros etc]$ vim inittab
mount用法具体可参考:mount参数说明 # /etc/inittab # mount all the file systems specified in /etc/fstab (fstab接下来会创建) ::sysinit:/bin/mount -a #Use mdev as hotplug to auto mount USB storage or SD card (mdev进行设备热拔插管理) ::sysinit:/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug #Use mdev to auto generate the device node in /dev path #mdev通过proc和sys文件系统来动态整理出注册的设备,进而到/dev/下生成他们对应的节点, ::sysinit:/sbin/mdev -s #make shm, pts support ::sysinit:/bin/mkdir -p /dev/pts ::sysinit:/bin/mkdir -p /dev/shm #pts是远程虚拟终端。devpts即远程虚拟终端文件设备。通过/dev/pts可以了解目前远程虚拟终端的基本情况。(devpts和proc一样,是虚拟文件系系) ::sysinit:/bin/mount -t devpts devpts /dev/pts #Mount our apps/info partition null::wait:/bin/mount -o sync,noatime,ro -t jffs2 /dev/mtdblock6 /apps null::wait:/bin/mount -o sync,noatime,ro -t jffs2 /dev/mtdblock7 /info #Set hostname (-F表示文件,从文件读取hostname) null::sysinit:/bin/hostname -F /etc/hostname #Enable console logon(设置终端信息) null::respawn:/sbin/getty -L ttyS0 115200 vt100 # now run any rc scripts(首先执行rcS) null::wait:/etc/init.d/rcS # system daemon #​syslogd记录应用程序或者设备的日志的进程 null::respawn:/sbin/syslogd -n #klogd截获并记录 Linux 内核消息的守护进程禁止自动后台运行,在 klogd 由 init 启动并直接被 init 控制的情况下必须使用此开关。 null::respawn:/sbin/klogd -n # Stuff to do before rebooting(重启) null::shutdown:/bin/umount /apps null::shutdown:/bin/umount /info null::shutdown:/bin/killall klogd null::shutdown:/bin/killall syslogd #杀死进程 null::shutdown:/bin/umount -a -r #null::shutdown:/sbin/swapoff -a 常见的action如下所示:
  • initdefault: 该配置项指定系统的默认运行级。
  • respawn: 该配置项所指定的进程如果被结束,则重新启动该进程。
  • wait: 该配置项指定的进程在运行结束之前不要执行下一条配置项
  • once: 切换到对应的运行级之后,仅执行指定的进程一次。
  • sysinit: 无论以什么运行级启动,系统启动时都要执行该配置项指定的进程。
  • boot: 仅在系统启动时执行一次。
  • bootwait: 仅在系统启动时执行一次,在执行结束之前不执行下一条配置项
  • powerfail: 当接收到UPS的断电通知时执行该项指定的进程。
  • powerwait: 与powerfail相同,但init会等待进程执行结束。
  • powerokwait: 接收到UPS的供电通知时执行。
  • ctrlaltdel: 当用户同时按下 Ctrl+Alt+Del 时执行该项指定的进程。

2、创建etc/init.d/rcS脚本

上面的inittab文件中,linux启动会调用这个脚本,这个脚本很简单。功能也很容易理解。
[yangni@Certoros etc]$ vim init.d/rcS #!/bin/sh #function:在/etc/init.d/目录下,凡是碰到以大写S打头的文件,就执行它,所以如果想写一个脚本实现开机自启动的话,就可以放在该目录下,并把文件名命名为大写S打头 for i in /etc/init.d/S??* ; do $i done

3、配置网卡自启脚本:

[yangni@Certoros etc]$ vim init.d/S01_network #!/bin/sh ifconfig eth0 192.168.1.111 netmask 255.255.255.0 up 因为改脚本放在init.d目录下,所开机会实现自启动。

4、创建支持/apps/etc目录下的启动脚本

[yangni@Certoros etc]$ vim init.d/S99_rcsApp #!/bin/sh if (test -d /apps/etc/init.d) ##如果是一个目录 then for i in /apps/etc/init.d/S??* ; do $i done fi 这里一样的意思,该文件目录下也可以实现自启动。以便于用户实现应用程序的自启动,不要跟系统自启动脚本混在一起。

5、修改init.d目录下所有文件权限

[yangni@Certoros etc]$ chmod 777 init.d/* [yangni@Certoros etc]$ ll init.d/ total 12 -rwxrwxrwx 1 Certoros trainning 222 Apr 26 13:27 rcS -rwxrwxrwx 1 Certoros trainning 64 Apr 26 13:33 S01_network -rwxrwxrwx 1 Certoros trainning 248 Apr 26 13:37 S99_rcsApp

6、创建fstab文件

linux启动脚本中用命令mount -a会一次对fstab中设备进行挂载。
fstab文件中的纪录的排序十分重要。因为fsck,mount或umount等程序在做它们的工作时会按此顺序进行。
[yangni@Certoros etc]$ vim fstab #devpts /dev/pts devpts defaults 0 0 #/dev/root / ext2 rw,noauto 0 1 proc /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 tmpfs /dev tmpfs defaults 0 0 sysfs /sys sysfs defaults 0 0

7、创建hostname,hosts,TZ文件

[yangni@Certoros etc]$ echo "root" > hostname [yangni@Certoros etc]$ echo "127.0.0.1 yangni" >> hosts #本机ip和主机名 [yangni@Certoros etc]$ echo "MST7MDT" >> TZ [yangni@Certoros etc]$ echo "Copyright (C) 2017 497049229@qq.com>" >> issue # 系统登录时的提示信息 注:
hosts文件: #文件格式: IPaddress hostname aliases 文件功能: 提供主机名到IP地址的对应关系,建议将自己经常使用的主机 加入此文件中,也可将没有DNS记录的机器加入到此文件中, 会方便网络应用 系统默认有以下两条,建议保留: #cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 新添添加的必须有三个字段:{IP、FQDN(完全合格域名/全称域名)、HOSTNAME}      210.38.206.21 jx.sgu.edu.cn jx

8、 创建profile文件

profile用于设置环境变量,每次重启之后自动初始化。设置的环境变量对所有用户生效。
~/.bash_profile:每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件。~/.bash_profile只对当前用户生效。 ~/.bashrc:该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件被读取.(每个用户都有一个.bashrc文件,在用户目录下)不需要重启生效,重新打开一个bash即可生效, /etc/bashrc对所有用户新打开的bash都生效,但~/.bashrc只对当前用户新打开的bash生效。 [yangni@Certoros etc]$ vim profile # /etc/profile: system-wide .profile file for the Bourne shells. export PATH= #设置命令存放路径 代表接着紧接着下面写 /bin: /sbin: /usr/bin: /usr/sbin: /usr/local/bin: /apps/bin: /apps/tools: /apps/tslib/bin # If running interactively, then: if [ "$PS1" ]; then if [ "$BASH" ]; then #/bin/bash export PS1="[u@h W]\$ " #ls命令颜 {MOD}设置 alias ll='/bin/ls --color=tty -laFh' alias ls='/bin/ls --color=tty -F' #终端颜 {MOD}设置 export LS_COLORS='no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01; 32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=0 1;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.png=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35 :*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.d l=01;35:*.xcf=01;35:*.xwd=01;35:'; else if [ "`id -u`" -eq 0 ]; then #id -u 等于0,表示为超级用户 export PS1='>: ' else export PS1='>: ' fi fi # System Setting set -o vi alias ll='ls -l' export USER=`id -un` #设置用户名变量 export LOGNAME=$USER export HOSTNAME=`/bin/hostname` #主机名 export HISTSIZE=1000 #历史记录显示最大条数 export HISTFILESIZE=1000 export PAGER='/bin/more ' export EDITOR='/bin/vi' export INPUTRC=/etc/inputrc #文件为特定的情况处理键盘映射,这个文件被 Readline 用作启动文件 #调试用于输出信息 export DMALLOC_OPTIONS=debug=0x34f47d83,inter=100,log=logfile export VAR1= export VAR2= export VAR3= export VAR4= export VAR5= export LD_LIBRARY_PATH=/lib:/usr/lib/ #链接库的地址 # QT Extendded 4.4.3 Setting export QTDIR=/apps/qt-extended-4.4.3 export QWS_MOUSE_PROTO='TSLIB:/dev/event0' export QWS_DISPLAY='LinuxFB:/dev/fb0' export QWS_DISPLAY='LinuxFB:mmWidth240:mmHeight320:0' export QWS_SIZE='240x320' export QT_PLUGIN_PATH=$QTDIR/plugins/ export QT_QWS_FONTDIR=$QTDIR/lib/fonts export PATH=$QTDIR/bin:$PATH export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QTDIR/lib # Touch Scree tslib Setting export TSLIB_ROOT=/apps/tslib export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf export TSLIB_CALIBFILE=$TSLIB_ROOT/etc/pointercal export TSLIB_TSDEVICE=/dev/event0 export TSLIB_CONSOLEDEVICE=none export TSLIB_FBDEVICE=/dev/fb0 fi; 关于环境变量一些参考文档:
1、终端颜 {MOD}:参考终端颜 {MOD}设置
2、PS1变量: PS1='[u@h w A ##]$ ' # d ∶代表日期,格式为 Weekday Month Date,例如 "Mon Aug 1" # H ∶完整的主机名称。举例来说,鸟哥的练习机 linux.dmtsai.tw ,那么这个主机名称就是 linux.dmtsai.tw # h ∶仅取主机名称的第一个名字。以上述来讲,就是 linux 而已, .dmtsai.tw 被省略。 # ∶显示时间,为 24 小时格式,如∶ HH:MM:SS # T ∶显示时间,12 小时的时间格式! # A ∶显示时间,24 小时格式, HH:MM # u ∶目前使用者的帐号名称; # v ∶BASH 的版本资讯; # w ∶完整的工作目录名称。家目录会以 ~ 取代; # W ∶利用 basename 取得工作目录名称,所以仅会列出最后一个目录名。 # # ∶下达的第几个指令。 # $ ∶提示字元,如果是 root 时,提示字元为 # 3、tslib是一个开源的程序,能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能,通常作为触摸屏驱动的适配层,为上层的应用提供了一个统一的接口。

9、创建指定一些协议所使用的端口号文件protocols

该文件是网络协议定义文件,里面记录了TCP/IP协议族的所有协议类型。文件中的每一行对应一个协议类型,它有3个字段,中间用TAB或空格分隔,分别表示“协议名称”、“协议号”和“协议别名”。 [yangni@Certoros etc]$ vim protocols # /etc/protocols: # $Id: protocols,v 1.1.1.1 2001/09/12 19:03:24 andersee Exp $ # # Internet (IP) protocols # # from: @(#)protocols 5.1 (Berkeley) 4/17/89 # # Updated for NetBSD based on RFC 1340, Assigned Numbers (July 1992). ip 0 IP # internet protocol, pseudo protocol number icmp 1 ICMP # internet control message protocol igmp 2 IGMP # Internet Group Management ggp 3 GGP # gateway-gateway protocol ipencap 4 IP-ENCAP # IP encapsulated in IP (officially ``IP'') st 5 ST # ST datagram mode tcp 6 TCP # transmission control protocol egp 8 EGP # exterior gateway protocol pup 12 PUP # PARC universal packet protocol udp 17 UDP # user datagram protocol hmp 20 HMP # host monitoring protocol xns-idp 22 XNS-IDP # Xerox NS IDP rdp 27 RDP # "reliable datagram" protocol iso-tp4 29 ISO-TP4 # ISO Transport Protocol class 4 xtp 36 XTP # Xpress Tranfer Protocol ddp 37 DDP # Datagram Delivery Protocol idpr-cmtp 39 IDPR-CMTP # IDPR Control Message Transport rspf 73 RSPF #Radio Shortest Path First. vmtp 81 VMTP # Versatile Message Transport ospf 89 OSPFIGP # Open Shortest Path First IGP ipip 94 IPIP # Yet Another IP encapsulation encap 98 ENCAP # Yet Another IP encapsulation

10、创建mdev.conf文件

  mdev命令会在/etc目录下找mdev的配置文件: mdev.conf. 如果该文件不存在,那么在执行mdev –s这个命令时,会提示找不到mdev.conf,这时我们可以建一个空的mdev.conf文件解决这个问题。下面创建使用mdev自动挂载u盘和SD卡的配置/etc/mdev.conf 参考:mdev.conf配置规则
使用 mdev 的可选配置文件,以控制设备节点的 所有者 和 权限。
这个文件的格式如下:
:
例如:
hd[a-z][0-9]* 0:3 660 [yangni@Certoros etc]$ vim mdev.conf sd[a-z][0-9] 0:0 0777 @(mount /dev/$MDEV /mnt/usb) sd[a-z] 0:0 0777 $(umount /mnt/usb) ub[a-z][0-9] 0:0 0777 @(mount /dev/$MDEV /mnt/usb) ub[a-z] 0:0 0777 $(umount /mnt/usb) mmcblk[0-9]p[0-9] 0:0 0777 @(mount /dev/$MDEV /mnt/sdc) mmcblk[0-9] 0:0 0777 $(umount /mnt/sdc)

11、 创建用户组group文件

[yangni@Certoros etc]$ vim group root:x:0:root 它的格式如下:
groupname : password : gid : members
  • 第一个字段为用户组名称
  • 第二个字段为用户组密码,当为x时密码是映射到/etc/gshadow中的,是非逆的
  • 第三个字段为GID,即组号,为正整数或0,0**被付于了root用户组;系统通常会预留一些较靠前的GID给系统虚拟用户之用,每个系统预留的GID都不同,Fedora预留了500个,所以我们添加新用户组时是从500开始的**。GID的范围由/etc/login.defs中的GID_MIN和GID_MAX决定
  • 第四个字段为用户列表,每个用户间用逗号分隔这里的password代表组口令,很少用到。它可使原先不在这个群组中的用户可以通newgrp命令暂时继承该组的权限,使用 newgrp命令时会新开一个shell。口令的加密方式和passwd文件中的口令一样,所以如果需设置组口令,要用passwd程序虚设一个用户,再把该用户password节中的加密口令拷贝到/etc/group文件中。members列代表组成员,我们可把需加入该组的用户以逗号分隔添加到这里即可。同一组的成员可继承该组所拥有的权限。

12、创建用户passwd文件:

[yangni@Certoros etc]$ vim passwd root:x:0:0:root:/:/bin/sh 它的格式如下:
username:password:uid:gid:gecos:homedir:shell
  • 第一个字段为登录名
  • 第二个字段为口令,一般被映射到shadow文件中
  • 第三个字段为UID (user id)
  • 第四个字段为GID(group id)
  • 第五个字段为用户名全称,gecos是通用电子计算机操作系统的缩写,是Bell实验室中的一台大型主机。
  • 第六个字段为用户根目录
  • 第七个字段为用户所用SHELL的类型
  Unix系统最初是用明文保存密码的,后来由于安全的考虑,采用crypt()算法加密密码并存放在/etc/passwd文件。现在,由于计算机处理能力的提高,使密码破解变得越来越容易。/etc/passwd文件是所有合法用户都可访问的,大家都可互相看到密码的加密字符串,这给系统带来很大的安全威胁。现代的Unix系统使用影子密码系统,它把密码从/etc/passwd文件中分离出来,真正的密码保存在/etc/shadow文件中,shadow文件只能由超级用户访问。这样入侵者就不能获得加密密码串,用于破解。使用shadow密码文件后,/etc/passwd文件中所有帐户的password域的内容为”x”,如果password域的内容为”*”,则该帐号被停用。使用passwd这个程序可修改用户的密码。

13、创建密码映射shadow文件

[yangni@Certoros etc]$ vim shadow root:($jGZIHmtT$y8ZXoPllK12/wl51kMw4e/:0:0:99999:7:::)# 显示的是加密后的字符串 该文件我们可以在Linux系统上使用passwd命令修改root口令来获取:
[lingyun@localhost ~]$ passwd root Changing password for user root. New UNIX password: Retype new UNIX password: passwd: all authentication tokens updated successfully. [yangni@Certoros etc]$ cat /etc/shadow | grep root root:$1$jGZIHmtT$y8ZXoPllK12/wl51kMw4e/:0:0:99999:7::: 当然,在设置为嵌入式平台上的root口令后,最好把系统上的root命令恢复到原始密码。
他的格式如下:
username : password : last_change:min_change : max_change : warm : failed_expire : expiration:reserved
  • 第一字段:用户名(也被称为登录名),在/etc/shadow中,用户名和/etc/passwd 是相同的,这样就把passwd 和shadow中用的用户记录联系在一起;这个字段是非空的;
  • 第二字段:密码(已被加密),这个字段是非空的;
  • 第三字段:上次修改口令的时间;这个时间是从1970年01月01日算起到最近一次修改口令的时间间隔(天数),您可以通过passwd 来修改用户的密码,然后查看/etc/shadow中此字段的变化;
  • 第四字段:两次修改口令间隔最少的天数;如果这个字段的值为空,帐号永久可用;
  • 第五字段:两次修改口令间隔最多的天数;如果这个字段的值为空,帐号永久可用;
  • 第六字段:提前多少天警告用户口令将过期;如果这个字段的值为空,帐号永久可用;
  • 第七字段:在口令过期之后多少天禁用此用户;如果这个字段的值为空,帐号永久可用;
  • 第八字段:用户过期日期;此字段指定了用户作废的天数(从1970年的1月1日开始的天数),如果这个字段的值为空,帐号永久可用;
    第九字段:保留字段,目前为空,以备将来发展之用;
这里我们设置为不用密码登陆,将password格式的内容清空:
[yangni@Ce