树莓派开发—文件系统


前言

根据我们以前的认知,认为Linux中文件系统就是指根文件目录,但实际上是这样吗?

我们知道在Windows系统中,单独的文件系统由驱动器名称(如:A,B,C…)来标识,每个单独的磁盘即一个分区,而在Linux系统中是怎么的呢?

在应用层,不管我们对什么类型的文件进行操作,都是采用open(),close(),read(),write()等函数进行操作,这与文件系统又有什么关系呢?

一、文件系统相关概念

1.文件系统

文件系统(FS):是指用来方便管理文件和组织数据的一种方法。简而言之,文件系统可看作一个程序,这个程序的功能就是对存储设备的扇区进行管理,将对这些扇区的访问变成了对目录和文件名的访问。我们在上层按照特定的目录和文件名去访问一个文件时,文件系统会将这个目录+文件名转换成对扇区号的访问。

如Windows下的FAT、FAT32、NTFS,Linux下的Ext2,Ext3,Ext4,vfat,jffs,ramfs,nfs等,这些应该都属于这个概念。

2.根文件系统

根文件系统(RFS) 可看作是一种特殊的文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于普通的文件系统,它的特殊之处在于,它是内核启动时所挂载(mount)的第一个文件系统,内核代码的映像文件保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本(如rcS,inittab)和服务加载到内存中去运行。

根文件系统是如何挂载的呢?
内核通过一系列初始化之后,挂载根文件系统来执行应用程序。所谓根文件系统,需要提前按照一定的文件系统进行格式化,并放入相应的内容数据。Kernel 根据启动参数去寻找根文件系统的位置去mount。

具体来说:先将/dev/ram0挂载,而后执行/linuxrc,等其执行完后,切换根目录,再挂载具体的根文件系统。根文件系统执行完之后,也就是到了start_kernel()函数的最后,执行init的进程,也就第一个用户进程,对系统进行各种初始化的操作。

根文件系统通俗解释: 根文件系统之所以在前面加一个”根“,说明它是加载其它文件系统的”根“,既然是根的话,那么如果没有这个根,其它的文件系统也就没有办法进行加载。它包含系统引导和使其他文件系统得以挂载(mount)所必要的文件。根文件系统包括Linux启动时所必须的目录和关键性的文件,例如Linux启动时都需要有init目录下的相关文件,在 Linux挂载分区时Linux一定会找/etc/fstab这个挂载文件等,根文件系统中还包括了许多的应用程序bin目录等,任何包括这些Linux 系统启动所必须的文件都可以成为根文件系统。**Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。成功之后可以自动或手动挂载其他的文件系统。**因此,一个系统中可以同时存在不同的文件系统。在 Linux 中将一个文件系统与一个存储设备关联起来的过程称为挂载(mount)。使用 mount 命令将一个文件系统附着到当前文件系统层次结构中(根)。在执行挂装时,要提供文件系统类型、文件系统和一个挂装点。根文件系统被挂载到根目录下“/”上后,在根目录下就有根文件系统的各个目录,文件:/bin /sbin /mnt等,再将其他分区挂接到/mnt目录上,/mnt目录下就有这个分区的各个目录、文件。

“鸡生蛋蛋生鸡”
内核刚启动时,磁盘设备、网络设备都还没有被驱动起来,所以无法访问磁盘,没法给磁盘启用对应的文件系统。那赶紧安装磁盘驱动程序,网络驱动程序呀,怎么不加载呢?因为磁盘种类太多了,没法把所有的驱动都编译到内核里头,那样内核得变得多大呀,所以就只能把这些驱动程序编译成模块的方式,在内核加载的时候现场判断当前用的是什么磁盘再加相应的磁盘驱动模块。那就加载磁盘驱动模块呀,等什么呢?原因是编译成驱动模块后,在这个阶段压根就没法加载!还没文件系统呢,怎么加载驱动模块?结果启用文件系统的前提是磁盘的驱动程序已经加载,而驱动程序的加载的前提是已经有文件系统存在,这就成了鸡生蛋,蛋生鸡的问题,怎么破?

想到内核加载的时候,RAM其实已经可用了,那就基于RAM建立一个临时文件系统吧,这个临时的文件系统自己挂载到自己身上,然后我们指定这个文件系统为根文件系统,这样就有了起步的文件系统啦,借助这个临时的文件系统把磁盘驱动模块、网络驱动模块加载上,这样就可以挂载实际的文件系统啦,有了实际的文件系统之后再把这个实际的文件系统指定为根文件系统,这就好啦,然后其他的各式各样的文件系统就可以陆陆续续的挂载在这个根文件系统下了。

回到之前的一个问题,怎么建立一个基于RAM的临时文件系统?首先,在编译内核得时候就编译一个很精简的临时文件系统进去,然后内核在启动的时候先注册一个rootfs这个临时文件系统,然后挂载这个临时文件系统,那rootfs这个临时文件还是个空的,得给里头放点东西呀,放什么呢?就放编译进内核里头的那个很精简的临时文件系统里的内容。怎么内容放进rootfs里去?方法简单粗暴,直接把编译进内核里头的那个很精简的临时文件系统里的内容解压到rootfs里,这个过程叫填充rootfs。(原文用的字眼是虚拟文件系统,而非临时文件系统)

转载自:
Linux内核与根文件系统的关系详解
根文件系统理解

3.虚拟文件系统

虚拟文件系统在后面进行具体介绍。

二、Linux文件系统结构

Linux下的文件系统结构如下:
在这里插入图片描述

1. 硬盘驱动(Device Driver)

常见的硬盘类型有PATA、SATA、AHCI等,在Linux系统中,对不同硬盘所提供的驱动模块一般都存放在内核目录树drivers/ata中,而对于一般通用的硬盘驱动,也许会直接被编译到内核中,而不会以模块的方式出现,可以通过查看 /boot/config-xxx.xxx 文件来确认:CONFIG_SATA_AHCI=y

2. 通用块设备层(General Block Device Layer)

不同的硬盘驱动,会提供不同的IO接口,内核认为这种杂乱的接口,不利于管理,需要把这些接口抽象一下,形成一个统一的对外接口,这样,不管你是什么硬盘,什么驱动,对外而言,它们所提供的IO接口没什么区别,都一视同仁的被看作块设备来处理。

所以,如果在一层做的任何修改,将会直接影响到所有文件系统,不管是ext3,ext4还是其它文件系统,只要在这一层次做了某种修改,对它们都会产生影响。

3. 文件系统

文件系统这一层相信大家都再熟悉不过了,目前大多Linux发行版本默认使用的文件系统一般是ext4,另外,新一代的btrfs也呼之欲出,不管什么样的文件系统,都是由一系列的 mkfs.xxx 命令来创建,如:

mkfs.ext4 /dev/sda

mkfs.btrfs /dev/sdb

内核所支持的文件系统类型,可以通过内核目录树 fs 目录中的内容来查看。

4. 虚拟文件系统(Virtual File System)

试想,当我们通过 mkfs.xxx 系列命令创建了很多不同的文件系统,但这些文件系统都有各自的API接口,而用户想要的是,不管你是什么API,他们只关心mount/umount,或open/close等操作。

所以,VFS就把这些不同的文件系统做一个抽象,提供统一的API访问接口,这样,用户空间就不用关心不同文件系统中不一样的API了。VFS所提供的这些统一的API,再经过 System Call 包装一下,用户空间就可以经过SCI的系统调用来操作不同的文件系统。

VFS所提供的常用API有:

mount()
umount()

open()
close()

mkdir()

参考文章:
Linux文件系统
linux内核结构图
Linux 文件系统详解

三、Linux磁盘分区和目录

Windows的文件结构是多个并列的树状结构,最顶部的是不同的磁盘(分区),如:C,D,E,F等。但是在linux中,无论操作系统管理几个磁盘分区,这样的目录树只有一个。从结构上讲,各个磁盘分区上的树型目录不一定是并列的。

Linux的文件结构是单个的树状结构可以用 tree 进行展示,在Ubuntu下安装tree(sudo apt-get install tree),并可通过命令来查看。

1. 目录和分区

每次安装系统的时候我们都会进行分区,Linux下磁盘分区和目录的关系如下:

  1. 任何一个分区都必须挂载到某个目录上。
  2. 目录是逻辑上的区分。分区是物理上的区分。
  3. 磁盘Linux分区都必须挂载到目录树中的某个具体的目录上才能进行读写操作。
  4. 根目录是所有Linux的文件和目录所在的地方,需要挂载上一个磁盘分区。

以下是我们可能存在的一种目录和分区关系:
在这里插入图片描述
Q:如何查看分区和目录及使用情况?

  1. fdisk查看硬盘分区表
  2. df:查看分区使用情况
  3. du: 查看文件占用空间情况

Q: 为什么要分区,如何分区?

  1. 可以把不同资料,分别放入不同分区中管理,降低风险。
  2. 大硬盘搜索范围大,效率低
  3. 磁盘配合只能对分区做设定
  4. /home /var /usr/local经常是单独分区,因为经常会操作,容易产生碎片

2. 常见目录解释

/bin 二进制可执行命令
/dev 设备特殊文件

/etc 系统管理和配置文件
/etc/rc.d 启动的配置文件和脚本
/home 用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示
/lib 标准程序设计库,又叫动态链接共享库,作用类似windows里的.dll文件
/sbin 系统管理命令,这里存放的是系统管理员使用的管理程序
/tmp 公用的临时文件存储点
/root 系统管理员的主目录(呵呵,特权阶级)
/mnt 系统提供这个目录是让用户临时挂载其他的文件系统。
/lost+found 这个目录平时是空的,系统非正常关机而留下“无家可归”的文件(windows下叫什么.chk)就在这里
/proc 虚拟的目录,是系统内存的映射。可直接访问这个目录来获取系统信息。
/var 某些大文件的溢出区,比方说各种服务的日志文件
/usr 最庞大的目录,要用到的应用程序和文件几乎都在这个目录。其中包含:
   /usr/X11R6 存放X window的目录
   /usr/bin 众多的应用程序
   /usr/sbin 超级用户的一些管理程序
   /usr/doc linux文档
   /usr/include linux下开发和编译应用程序所需要的头文件
   /usr/lib 常用的动态链接库和软件包的配置文件
   /usr/man 帮助文档
   /usr/src 源代码,linux内核的源代码就放在/usr/src/linux里
   /usr/local/bin 本地增加的命令
   /usr/local/lib 本地增加的库
  
参考文章:
linux文件系统简介

Guess you like

Origin blog.csdn.net/little_rookie__/article/details/118650008