本文共 7757 字,大约阅读时间需要 25 分钟。
嵌入式Linux内核的块设备驱动:
对于linux
a)
b)
c) RAM disk
Blkmem
Linux的MTD驱动是标准Linux的Flash驱动。它支持大量的设备,有足够的功能来定义Flash的分区,进行地址映射等等。使用MTD你可以在一个系统中使用不同类型的Flash。它可以将不同的Flash组合成一个线性的地址让你来使用。
在标准的Linux 2.4内核中MTD有一系列的选项,你可以根据个人系统的需要来选择,定制。
另外一种选择就是RAM disk
MTD
NET4: Linux TCP/IP 1.0 for NET4.0 |
调用inet_init [ linux-2.4.22\net\ipv4\Af_inet.c ]时的输出信息,
IP Protocols: ICMP, UDP, TCP, IGMP |
列出可以支持的IP协议,此处为kernel源代码inet_add_protocol(p);的输出。
在linux启动过程中,都会看到这句的输出。
IP: routing cache hash table of 512 buckets, 4Kbytes |
IP路由代码的输出信息。
ip_rt_init [ linux-2.4.22\net\ipv4\Route.c ],Set the IP module up,路由缓冲hash表
TCP: Hash tables configured (established 8192 bind 8192) |
TCP协议初始化输出信息。tcp_init [ linux-2.4.22\net\ipv4\Tcp.c ],
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. |
UNIX网络协议信息。
af_unix_init[ linux-2.4.22\net\unix\Af_unix.c ],
上面的关于网络的输出信息是在linux启动信息中都会出现的。
加载各种文件系统
cramfs: wrong magic |
会出现“cramfs: wrong magic”,别担心这没有什么害处,这个是kernel的书写bug,在2.6中有修改之,它是一个警告信息,用来检查cramfs的superblock超级块的。superblock也是VFS要用到的数据结构。
代码linux-2.4.22\fs\cramfs\Inode.c:
2.4 cramfs_read_super(。。。) |
2.6 if (super.magic != CRAMFS_MAGIC) { |
超级块是文件系统的“头部”。它包含文件系统的状态、尺寸和空闲磁盘块等信息。如果损坏了一个文件系统的超级块(例如不小心直接将数据写到了文件系统的超级块分区中),那么系统可能会完全不识别该文件系统,这样也就不能安装它了,即使采用e2fsck
Cramfs文件系统:
cramfs
我们制作image文件之后,我们还要考虑怎样才能在系统运行的时候,把这个
mount -o loop -t cramfs /usr.img /usr
这样,就可以经由
cramfs
Cramfs通过优化索引节点表的尺寸和除去传统文件系统中文件之间的空间浪费来达到节约空间的目的。它还使用了zlib压缩,实现优于2:1的压缩比例。解压缩过程的系统开销并不是很大,因为Cramfs支持指定单块的解压,而并不必解压缩整个文件。
Cramfs不仅能节省空间,还能避免非正常关机导致的等待fsck或手工进行fsck的麻烦。它通过只读的方式达到这一目的。
RamDisk有三种实现方式:
在Linux中可以将一部分内存mount为分区来使用,通常称之为RamDisk,分为:
Ramdisk, ramfs, tmpfs.
①
这在Linux内核2.0/2.2就已经支持,其不足之处是大小固定,之后不能改变。
为了能够使用Ramdisk,我们在编译内核时须将block device中的Ramdisk支持选上,它下面还有两个选项,一个是设定Ramdisk的大小,默认是4096k;另一个是initrd的支持。
如果对Ramdisk的支持已经编译进内核,我们就可以使用它了:
首先查看一下可用的RamDisk,使用ls /dev/ram*
首先创建一个目录,比如test,运行mkdir /mnt/test;
然后对/dev/ram0
最后挂载
②
它们不需经过格式化,用起来灵活,其大小随所需要的空间而增加或减少。
Ramfs顾名思义是内存文件系统,它处于虚拟文件系统(VFS)层,而不像ramdisk那样基于虚拟在内存中的其他文件系统(ex2fs)。
因而,它无需格式化,可以创建多个,只要内存足够,在创建时可以指定其最大能使用的内存大小。
如果你的Linux已经将Ramfs编译进内核,你就可以很容易地使用Ramfs了。创建一个目录,加载Ramfs到该目录即可:
# mkdir /testRam
# mount -t ramfs none /testRAM
缺省情况下,Ramfs被限制最多可使用内存大小的一半。可以通过maxsize(以kbyte为单位)选项来改变。
# mount -t ramfs none /testRAM -o maxsize=2000 (创建了一个限定最大使用内存为2M的ramdisk)
③
Tmpfs可以使用物理内存,也可以使用交换分区。在Linux内核中,虚拟内存资源由物理内存(RAM)和交换分区组成,这些资源是由内核中的虚拟内存子系统来负责分配和管理。
Tmpfs向虚拟内存子系统请求页来存储文件,它同Linux的其它请求页的部分一样,不知道分配给自己的页是在内存中还是在交换分区中。同Ramfs一样,其大小也不是固定的,而是随着所需要的空间而动态的增减。
使用tmpfs,首先你编译内核时得选择"虚拟内存文件系统支持(Virtual memory filesystem support)"。
然后就可以加载tmpfs文件系统了:
# mkdir -p /mnt/tmpfs
#
同样可以在加载时指定tmpfs文件系统大小的最大限制:
#
FAT: bogus logical sector size 21072 |
具体的文件系统FAT格式。
虚拟逻辑扇区大小为20K,linux-2.4.22\fs\fat\Inode.c。
在初始化MS-DOS文件系统时,读MS-DOS文件系统的superblock,函数fat_read_super中输出的上面的信息。
UMSDOS: msdos_read_super failed, mount aborted. |
UMSDOS:一种文件系统,特点容量大但相对而言不大稳定。是Linux
VFS: Mounted root (romfs filesystem) readonly |
虚拟文件系统VFS(Virtual Filesystem Switch)的输出信息。
再次强调一下一个概念。VFS
Mounted devfs on /dev |
加载devfs设备管理文件系统到dev安装点上。
/dev是我们经常会用到的一个目录。
在2.4的kernel中才有使用到。每次启动时内核会自动挂载devfs。
devfs提供了访问内核设备的命名空间。它并不是建立或更改设备节点,devfs只是为你的特别文件系统进行维护。一般我们可以手工mknod创件设备节点。/dev目录最初是空的,里面特定的文件是在系统启动时、或是加载模组后驱动程序载入时建立的。当模组和驱动程序卸载时,文件就消失了。
Freeing init memory: 72K |
释放1号用户进程init所占用的内存。
第三节:加载linux内核完毕,转入cpu_idle进程
系统启动过程中进程情况:
①init进程
一般来说,
你可以用进程查看命令来验证 # ps aux PID Uid VmSize Stat Command 1 0 SW init 2 0 SW [keventd] 3 0 SWN [ksoftirqd_CPU0] 4 0 SW [kswapd] 5 0 SW [bdflush] 6 0 SW [kupdated] 7 0 SW [rbwdg] 9 0 SW [mtdblockd] 10 0 SW [khubd] 80 0 SW [loop0] |
另外
只有这个
init有许多很重要的任务,比如象启动getty(用于用户登录)、实现运行级别、以及处理孤立进程。
init
一般,
②
A>
这些进程就是内核守护进程。大部分内核并不显示在进程列表里。守护进程在init之后启动,所以他们和其他进程一样有进程ID,但是他们的代码和数据都存放在内核占有的内存中。在列表中使用中括号来区别与其他进程。
B>
C>
D> bdflush - BUF_DIRTY,
E> ksoftirqd_CPUx
ksoftirqd_CPUx是由cpu_raise_softirq()即cpu触发中断,唤醒的内核线程,这涉及到软中断,ksoftirqd的代码参见
F> keventd,它的任务就是执行
G> khubd,
H> mtdblockd是用来对flash块设备进行写操作的守护进程。
NAND类型的Flash需要MTD(Memory Technology Devices
NAND的特点是不能在芯片内执行(XIP,eXecute In Place),需要把代码读到系统RAM中再执行,传输效率不是最高,最大擦写次数量为一百万次,但写入和擦除的速度很快,擦除单元小,是高数据存储密度的最佳选择。
NAND需要I/O接口,因此使用时需要驱动程序。
I> loop0
loopback设备和其他的块设备的使用方法相同。特别的是,可以在该设备上建立一个文件系统,然后利用mount命令把该系统映射到某个目录下以便访问。这种整个建立在一个普通磁盘文件上的文件系统,就是虚拟文件系统
总结:
上面的内容是本人为了在实际开发中更加清楚地了解嵌入式linux的启动过程而做的一个总结性的文章。
在对嵌入式linux的启动过程做了一个详细注释后,大家会对涉及到嵌入系统的各个概念有了一个更加明确的认识,并能对嵌入系统的软硬件环境的有关设置更加清楚。当你自己动手结合linux源代码来分析时,将会有一个清楚的全局观。
现在,你如果再回头去看文章前面所列出的启动信息例子中的内容,其中80%的内容,你现在应该能看懂它的来龙去脉了。
转载地址:http://sapci.baihongyu.com/