Linux文件系统——ramdisk根文件系统制作

ram disk介绍

  ram disk顾名思义,内存磁盘。我们平常接触的一些存储介质,如:nor flash、nand flash、emmc、ufs、以及机械硬盘固态硬盘等,都是用来存储数据的,同理内存也是可以当成磁盘来存储数据的,唯一不同的就是ram是掉电不保存的,而前面提到的那些存储介质掉电都是保存数据的。
  我们都知道,在linux中,上面介绍的flash这些存储介质,都是需要有对应的驱动,注册成块设备。并向上层提供接口。如nor、nand等都抽象成mtdblock块设备。
  同理,linux中的ram disk意思就是拿出ram中的一部分大小,用对应的驱动注册层块设备,提供给上层调用。一般的ram disk注册成的块设备,在文件系统中设备节点提现为/dev/ramx。

ramdisk文件系统介绍

  介绍ramdisk文件系统前,先来看一下一般linux文件系统,这里以我的ubuntu16.04虚拟机为例:

root@ubuntu:~# mount
......
/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
......

  这里我省略了很多其他的挂载点,就生了根目录挂载点,可以看到根目录挂载在/dev/sda1上,/dev/sda是指接在SATA、SCSI第一个接口上的硬盘,所以这里表示根目录挂载在sda块设备的sda1分区上。文件系统格式是ext4。
  然后再来看使用ramdisk文件系统启动的设备根目录挂载点:

[root@linux:/root]# mount
/dev/root on / type ext2 (rw,relatime,block_validity,barrier,user_xattr,acl,errors=remount-ro)
......

[root@linux:/root]# readlink /dev/root 
ram0

  可以看到,根目录挂载在/dev/root设备节点上,文件系统格式是ext2。然后通过查看/dev/root链接关系,看到/dev/root其实就是/dev/ram0。所以看到这里,就可以和上面虚拟机的根目录挂载联系起来了,其实本质一样,只是虚拟机挂载的是物理磁盘,我们的ramdisk文件系统挂载在ram磁盘上。因为ram掉电不保存,所以ramdisk文件系统掉电不保存数据。
  当然这个挂载根目录不是简单的挂载,需要有根文件系统,根文件系统需要init进程可执行文件等。下面进入正文,制作一个最简单的ramdisk文件系统。

ramdisk文件系统制作

一、配置内核支持ramdisk。

  执行make menuconfig,进入内核配置界面。

General setup  ---> 
	[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

  这里的意思是配置内核初始化时,去寻找initramfs和initrd,initrd就是我们的ramdisk文件系统,至于initramfs,后面有机会再介绍。

Device Drivers  ---> 
	<*>   RAM block device support
	(1)     Default number of RAM disks
	(65536) Default RAM disk size (kbytes)

  勾选第一项RAM block device support,才会出来第二项和第三项的选项。第一项的意思是内核支持ram disk块设备驱动。
  第二项是注册的块设备数量,内核默认是16,我这里就写了1,内核启动后会有/dev/ram0块设备节点,配置16则会有/dev/ram0~ram15。
  第三项的意思是ram disk占得最大内存,这里我写的是64M,一般来说可以写的再小点。实际在使用/dev/ramx设备时,并不是一下子就占系统64M内存,而是根据实际使用情况而分配的。

File systems  --->   
	<*> Second extended fs support 
	[*]   Ext2 extended attributes
	[*]     Ext2 POSIX Access Control Lists
	[*]     Ext2 Security Labels 

  勾选对ext2文件系统的支持,因为我们的ramdisk格式是ext2的,所以需要勾选对ext2文件系统格式的支持。勾选第一项才能勾选第二项,勾选第二项才能勾选三四项,总之都勾上都对了。
  其实此选项不勾选也不要紧,在不勾选< > Second extended fs support情况下,内核会自动勾选[*] Use ext4 for ext2 file systems配置项,用ext4去兼容ext2格式。

二、根文件系统的制作

开发环境:ubuntu16.04
注:以下操作都在root权限下执行

(1)建立目录

创建根文件系统一些基本目录

# mkdir ramdiskfs
# cd ramdiskfs/
# mkdir mnt tmp var usr sys proc etc lib dev bin sbin root home
# mkdir usr/lib lib/modules

创建部分设备节点

# sudo mknod -m 666 console c 5 1	//创建控制台设备文件
# sudo mknod -m 666 null c 1 3		//创建一个空的设备文件

拷贝配置文件
复制busybox中的/examples/bootfloppy/etc的文件

ramdiskfs# cp ../busybox-1.31.1/examples/bootfloppy/etc/ etc/ -rf

(2)busybox编译

  下载busybox,网站https://busybox.net/downloads/,这里我下载的busybox是:busybox-1.31.1.tar.bz2,版本1.31.1。
  解压busybox

# tar -xjf busybox-1.31.1.tar.bz2 
# cd busybox-1.31.1/

  配置busybox,这里我们用默认配置就好,执行

# make menuconfig

  配置如下项:

Settings  ---> 
	(../ramdiskfs) Destination path for 'make install'
	(arm-linux-gnueabi-) Cross compiler prefix 
	--- Build Options
	[*] Build static binary (no shared libs) 

分别为:
(1)设置安装目录,这里我的ramdisk和busybox-1.31.1同一目录下
(2)设置交叉编译工具链,前提是环境变量中有交叉编译工具路径才行。交叉编译工具链也可在Makefile中指定。
(3)设置静态编译(这里我们只做一个最简单的根文件系统,就不找动态库了,所有可执行文件静态编译)。

  编译busybox

# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8	//上面制定了编译工具链这里就可以直接make —j8,
														//我电脑是四核的所以-j8就行了,如果是8核就可以-j16加快编译速度,以此类推
# make install	//安装编译完的可执行文件等

  make install完成后,进到我们的ramdiskfs目录,可以看到根目录下linuxrc可执行文件,依次查看bin/ sbin/ usr/bin usr/sbin可以看到很多可执行命令。ls -l查看,可以看到所有可执行文件都是链接到bin/busybox上的。

(3)制作ramdisk根文件系统镜像、

  安装genext2fs工具

# apt-get install genext2fs

  cd到要制作的ramdiskfs的上一级目录

# genext2fs -b 4096 -d ramdsikfs ramdisk	(1)
# gzip –v9 ./ramdisk						(2)

(1)将ramdiskfs目录文件打包成ramdisk镜像。-b是大小4096代表4M,-d为需要打包的目录。最后ramdisk为生成的镜像文件名。注意这里打包的大小,需要小于之前内核中配置的Default RAM disk size,否则会出现kernel panic内核恐慌。
(2)使用gzip工具压缩ramdisk镜像,压缩完成后在当前目录下生成ramdisk.gz文件,不一定非要gzip压缩,也可以使用lzma格式等。lzma相对gz可以压缩的更小,但是内核启动时解压的时间也会变成,毕竟鱼和熊掌不可兼得。

(4)配置启动参数加载ramdisk

方法一:配置内核启动参数command line

  内核启动参数command line,可以有几种方式传递,一个通过uboot的bootargs传递,还有就是在内核中写死。
(1)内核中配置

# make menuconfig
Boot options  --->
	()  Default kernel command string

配置为console=ttyS0,115200 root=/dev/ram0 rw init=/linuxrc initrd=0x42000000 0x400000
最终在.config文件中体现为:COMFIG_CMDLINE=console=ttyS0,115200 root=/dev/ram0 rw init=/linuxrc initrd=0x42000000 0x400000
(2)uboot中配置bootargs
uboot下执行如下命令:
# setenv bootargs 'console=ttyS0,115200 root=/dev/ram0 rw init=/linuxrc initrd=0x42000000,0x400000'
# saveenv

  console=ttyS0,不同平台可能不一样,可能有ttyAMA、ttySAC等,根据具体情况写。
  root=/dev/ram0表示根目录挂载点为/dev/ram0块设备。init=/linuxrc表示init进程(1号进程)可执行文件为根目录下的linuxrc文件,在安装busybox时我们已经看到了根目录下的linuxrc文件。
initrd参数格式为:地址 长度,这里我的设备ram地址为0x40000000起始,随便挑了个地址加载,只要是在内核ddr物理地址空间内。长度这里只要比ramdisk.gz压缩包大小大就可以了。

方法二:bootm加载ramdisk.gz

  uboot在执行bootm命令加载uImage时,会对uImage 64字节数据头进行解析,进行校验。bootm加载uImage打印如下:

## Booting kernel from Legacy Image at 40008000 ...
   Image Name:   Linux-4.14.111
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    5855072 Bytes = 5.6 MiB
   Load Address: 40008000
   Entry Point:  40008000
   Verifying Checksum ... OK

  其实当bootm命令跟两个地址参数时,第二个地址就是加载ramdisk的地址。
  和加载uIamge时一样,bootm记载ramdisk时,也需要判断ramdisk.gz的 64字节数据头。所以用这种方法向内核传递ramdisk时,ramdisk.gz需要通过mkimage命令给ramdisk.gz加上64字节头。
命令如下:
mkimage -A arm -O linux -C gzip -T ramdisk -d ramdisk.gz ramdisk_1.gz
-A 架构类型 arm
-O 系统类型 linux
-C 压缩类型 gzip
-T 类型 ramdisk
执行完成后生成ramdisk_1.gz压缩包。
bootm加载ramdisk.gz打印如下:

## Loading init Ramdisk from Legacy Image at 42000000 ...
   Image Name:   
   Image Type:   ARM Linux RAMDisk Image (gzip compressed)
   Data Size:    2168875 Bytes = 2.1 MiB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK

(5)测试ramdisk.gz

  这里我使用上述第二种方式bootm传递,uboot设置环境变量

bootargs=console=ttyS0,115200 root=/dev/ram0 rw init=/linuxrc
tftp 0x40008000 uImage;tftp 0x41000000 ramdisk_1.gz;tftp 0x42000000 demo.dtb;

  最终启动效果如下

Processing /etc/profile... Done

/ # 
/ # 

  注意看一下内核找ramdisk的打印:

[    2.907900] RAMDISK: gzip image found at block 0
[    2.979402] EXT4-fs (ram0): mounting ext2 file system using the ext4 subsystem
[    2.987180] EXT4-fs warning (device ram0): ext4_update_dynamic_rev:795: updating to rev 1 because of new feature flag, running e2fsck is recommended
[    3.000863] EXT4-fs (ram0): mounted filesystem without journal. Opts: (null)
[    3.008109] VFS: Mounted root (ext2 filesystem) on device 1:0.

  至此,一个最简单的ramdisk文件系统制作完成。有空细讲一下具体进一步的/etc下配置,如何设置用户密码,磁盘挂载等。

你可能感兴趣的:(文件系统,Linux,Linux,文件系统,ramdisk)