根文件系统理解

article/2025/9/19 19:40:42

文件系统概念

 文件系统是一些代码,是一套软件,这套软件的功能就是对存储设备的扇区进行管理,将这些扇区的访问变成了对目录和文件名的访问。我们在上层按照特定的目录和文件名去访问一个文件时,文件系统会将这个目录+文件名转换成对扇区号的访问。

  • 虚拟文件系统接口(VFS)是linux定义的一个文件系统的统一接口,这样各种类型的文件系统都采用一样的接口给用户
  • 虚拟文件系统存储在RAM里的,没有实际的设备(ROM)与之对应
  • 实际文件系统有实际的存储设备(ROM)与之对应,又可分为远程文件系统和本地文件系统
  • 根文件系统处于文件系统的最上层,其很重要的作用是用来挂载其他文件系统。根文件系统可以是虚拟文件系统也可以是实际文件系统,只要条件支持.
  • 文件系统格式 linux支持包括ext2,ext3,vfat,jffs,ramfs,nfs等文件系统
    • jffs2:主要用于nor型flash,特点是可读写,支持数据压缩的日志型文件系统。
    • yaffs/yaffs2:主要用于nand型flash,支持跨平台。
    • cramfs:只读的压缩文件系统。可用于两种flash。
    • ramdisk:基于ram的文件系统。是将一部分固定大小的内存当做块设备来用。它并非是一个实际的文件系统,而是一种将实际的文件系统装入内存的机制。将一些经常访问而又无需更改的文件通过ramdisk放在内存中,可以明显的提高系统的性能。
    • initramfs:基于ram的文件系统。initramfs出现在2.6内核中,它类似于tmpfs,是一种基于内存的文件系统,它的使用不需要创建内存块设备。增加文件到ramfs会自动配置更多的内存,并删除或截去文件以释放内存。(若ramdisk没有满,已被占用的额外的内存也不能用来做其它事情,若ramdisk满了,但其它仍有闲置的内存,也必须重新格式化以后才能扩展使用)
    • nfs:是由sun开发的一种在不同机器之间通过网络共享文件的技术。在嵌入式linux系统的开发调试阶段,可以利用该技术在主机上建立基于nfs的根文件系统,挂载到嵌入式设备,可以很方便的修改根文件系统的内容。

为什么会有不同的文件类型?

 由于存储介质有很多种,所以没有办法用一种统一的格式存放文件系统到各种不同的存储介质上,而是需要多种不同的存储格式来适应各种存储介质的特性,以求达到存取效率和空间利用率的最优化,这样就需要对每种存储格式制定一个规范,这种规范就叫文件系统类型。

常见的文件系统类型有:

  • Dos:
    • FAT16
  • windows:
    • FAT16
    • FAT32
    • NTFS
  • Linux:
    • ext
    • ext2
    • ext3
    • ISO9660
    • jffs2, yaffs, yaffs2、cramfs, romfs, ramdisk, rootfs、proc、sysfs、usbfs、devpts、 tmpfs & ramfs、 NFS

由此可见,Linux支持的文件系统最多。以不同的介质来分类,如下所示:

  • 磁盘:FAT16、 FAT16、FAT32、NTFS、ext、ext2 、ext3、Minix
  • 光盘:ISO9660
  • Flash:jffs2、yaffs、yaffs2、cramfs、romfs
  • 内存:Ramdisk、tmpfs、ramfs
  • 虚拟:rootfs、proc、sysfs、usbfs、devpts、NFS

启动流程

 内核通过一系列初始化之后,挂载根文件系统来执行应用程序. 所谓根文件系统,需要提前按照一定的文件系统的格式化,并放入相应的内容数据.Kernel 根据启动参数去寻找根文件系统的位置去mount
在这里插入图片描述

根文件系统

ramdisk启动

 制作ramdisk文件系统压缩包然后将这个文件压缩包通过bootloader下载到内存中当系统启动的时候

  • 通过uboot的bootargs环境变量来传递启动参数,修改为bootargs=initrd=0x31000000,0x200000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64,以此指定从ramdisk启动,ramdisk压缩文件起始地址在内存地址0x31000000处,文件大小为0x200000。
  • 也可以通过修改内核配置Default kernel command string为”initrd=0x31000000,0x200000 root=/dev/ram rw init=/linuxrc console=ttySAC0 mem=64”

flash启动

 文件系统存在FLASH ,内核根据命令行参数root=/dev/xxx,直接mount。

问题? 在root文件系统本身还不存在的情况下,内核如何根据/dev/xxx来找到对应的设备呢?

 解答: 根文件系统和其他文件系统的mount方式是不一样的,内核通过直接解析设备的名称来获得设备的主、从设备号,然后就可以访问对应的设备驱动了。所以在init/main.c中有很长一串的root_dev_names(如hda,hdab,sda,sdb,nfs,ram,mtdblock……),通过这个表就可以根据设备名称得到设备号。注意,bootloader或内核中设定的启动参数root=/dev/xxx只是一个代号,实际的根文件系统中不一定存在这个设备文件!

 拿ARM来说,在文件arch/arm/plat-s3c24xx/common-smdk.c中有分区表(总大小–0x8000000–128MB):

static struct mtd_partition smdk_default_nand_part[] = {
[0] = {.name	= "Boot",.size	= 0x00020000,.offset	= 0,
},
[1] = {.name	= "Kernel",.size   = 0x00240000,.offset	= 0x00040000,
},
[2] = {.name	= "RootFileSystem",.size   = 0x02000000,.offset	= 0x00280000,
},
[3] = {.name	= "ExtendFileSystem",.size	= 0x05d80000,.offset	= 0x02280000,
}
};
名称开始地址结束地址文件大小
Boot00x200000x20000–128KB
Boot 参数区0x200000x400000x20000–128KB
Linux Kernel0x400000x2800000x240000–2304KB–2.25MB
根文件系统0x2800000x22800000x2000000–32768KB–32MB
其他文件系统0x22800000x80000000x5d80000–95744KB–93.5MB

对照Flash存储中存放文件的分布图如下图:
在这里插入图片描述

initramfs

 initramfs将根目录直接编译到linux内核镜像中 ,这种方法不同于前面两种方法需要在uboot启动参数中指定ramdisk加载到内存的地址或者文件系统在flash中的分区,由于已经将根目录编译到linux的.init.ramfs段中了,所以启动的时候直接将linux内核镜像的.init.ramfs段的内容解压到系统的rootfs中。

initrd

 启动时用到initrd来mount根文件系统。注意理解ramdisk和initrd这两个概念,其实ramdisk只是在ram上实现的块设备,类似与硬盘操作,但有更快的读写速度,它可以在系统运行的任何时候使用,而不仅仅是用于启动;

 initrd(boot loader initialized RAM disk)可以说是启动过程中用到的一种机制,具体的实现过程也使用ramdisk技术。就是在装载linux之前,bootloader可以把一个比较小的根文件系统的映象装载在内存的某个指定位置,姑且把这段内存称为initrd(这里是initrd所占的内存,不是ramdisk,注意区别),然后bootloader通过传递参数的方式告诉内核initrd的起始地址和大小(也可以把这些参数编译在内核中),在启动阶段就可以暂时的用initrd来mount根文件系统。initrd的最初的目的是为了把kernel的启动分成两个阶段:在kernel中保留最少最基本的启动代码,然后把对各种各样硬件设备的支持以模块的方式放在initrd中,这样就在启动过程中可以从initrd所mount的根文件系统中装载需要的模块。这样的一个好处就是在保持kernel不变的情况下,通过修改initrd中的内容就可以灵活的支持不同的硬件。在启动完成的最后阶段,根文件系统可以重新mount到其他设备上,但是也可以不再 重新mount(很多嵌入式系统就是这样)。 initrd的具体实现过程是这样的:bootloader把根文件系统映象装载到内存指定位置,把相关参数传递给内核,内核启动时把initrd中的内容复制到ramdisk中(ram0),把initrd占用的内存释放掉,在ram0上mount根文件系统。从这个过程可以看出,内核需要对同时对ramdisk和initrd的支持(这种需要都编入内核,不能作为模块)。

鸡生蛋蛋生鸡

 内核刚启动时,磁盘设备、网络设备都还没有被驱动起来,所以无法访问磁盘,没法给磁盘启用对应的文件系统。那赶紧安装磁盘驱动程序,网络驱动程序呀,怎么不加载呢?因为磁盘种类太多了,没法把所有的驱动都编译到内核里头,那样内核得变得多大呀,所以就只能把这些驱动程序编译成模块的方式,在内核加载的时候现场判断当前用的是什么磁盘再加相应的磁盘驱动模块。那就加载磁盘驱动模块呀,等什么呢?原因是编译成驱动模块后,在这个阶段压根就没法加载!还没文件系统呢,怎么加载驱动模块?结果启用文件系统的前提是磁盘的驱动程序已经加载,而驱动程序的加载的前提是已经有文件系统存在,这就成了鸡生蛋,蛋生鸡的问题,怎么破?想到内核加载的时候,RAM其实已经可用了,那就基于RAM建立一个临时文件系统吧,这个临时的文件系统自己挂载到自己身上,然后我们指定这个文件系统为根文件系统,这样就有了起步的文件系统啦,借助这个临时的文件系统把磁盘驱动模块、网络驱动模块加载上,这样就可以挂载实际的文件系统啦,有了实际的文件系统之后再把这个实际的文件系统指定为根文件系统,这就好啦,然后其他的各式各样的文件系统就可以陆陆续续的挂载在这个根文件系统下了。

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

https://www.cnblogs.com/zongzi10010/p/10023700.html


http://chatgpt.dhexx.cn/article/DJ8Euopp.shtml

相关文章

linux之根文件系统

前言 1、板卡上电后首先由UBOOT启动初始化板卡,将Linux内核移到内存中运行 2、由linux内核自行做了初始化等操作,挂在了第一个应用程序上(根文件系统/linuxrc) 3、根文件系统会提供磁盘管理服务,glibc设备节点&…

Linux:根文件系统构建

文章目录 一、编译 BusyBox 构建根文件系统1.创建BusyBox路径并解压2.修改顶层Makefile3.修改 busybox 源码4.配置busybox5.编译busybox6.向 rootfs 的“/lib”目录添加库文件7.向 rootfs 的“usr/lib”目录添加库文件创建其他文件夹 二、NFS挂载根文件系统1.bootargs 环境变量…

制作嵌入式Linux根文件系统

文章目录 1. 根文件系统布局2. 使用BusyBox生成二进制工具2-1. 获取BusyBox源码2-2. 配置BusyBox2-2-1. 选择编译静态库2-2-2. 选择交叉编译工具链2-2-3. 选择安装目录2-2-4. 编译安装 3. 构建根文件系统3-1. 完善目录结构3-2. 添加C运行库文件3-3. 添加初始化配置脚本3-3-1. 修…

[架构之路-30]:目标系统 - 系统软件 - Linux OS根文件系统rootfs的概念、组成、制作以及用busybox制作根文件系统

目录 前言: 第1章 什么是根文件系统 1.1 什么是文件 1.2 什么是文件系统 1.3 文件系统组织文件的方式:树形结构 1.4 统一的虚拟文件系统 1.5 物理存储介质与物理文件系统类型 1.5 什么是根文件系统 第2章 根文件系统的标准结构 2.1 根文件系统…

安装Ubuntu 16.04时出现:没有定义根文件系统,请到分区菜单修改

在安装Ubuntu 16.04时,尤其是选项空闲硬盘新建分区安装时,容易出现这种情况,这个是由于没有配置挂载点导致的,解决方法如下: 在挂在点输入“/”。 原理: Linux和Windows的文件系统不一样&#x…

Ubuntu提示“没有根文件系统 ”

安装Ubuntu时,提示“没有定义根文件系统” 原因:分区错误 解决: 将Ubuntu分区,删除重新创建分区,注意挂载点为“/” 此时就可以单击“继续”,进行下一步安装 以上分区方式,是没有交换分区的,下面提供两种带交换分区的分区方式: 第一种,包含4个分区,分别为 /分区(…

安装linux显示没有定义根文件系统,XP用Wubi安装Ubuntu提示“没有定义根文件系统,请返回分区菜单...

在安装Ubuntu时,到自定义分区一步时,会出现“没有根文件系统”,这时千万别将硬盘分区表重建,那样会让硬盘到数据都格式化到,你只需在ext4 或者 ext3 分区项上双击,加上挂载点为“\”就可以了。 有图有真相&…

在虚拟机安装中遇到的问题

问题一:在命令行模式下输入ifconfig时,显示系统不能识别这个命令,需要安装,输入sudo apt install net-tools。 问题二:sudo命令输入密码时,光标不移动,只要输入正确密码,回车就可以。…

安装Ubuntu时,提示“没有根文件系统 ”

安装Ubuntu时,提示“没有定义根文件系统” 原因:分区错误 解决: 将Ubuntu分区,删除重新创建分区,注意挂载点为“/” 此时就可以单击“继续”,进行下一步安装 以上分区方式,是没有交换分区的&a…

synchronized,voliate-详解

一.synchronized底层原理: synchronized关键字,在底层编译后的jvm指令中,会有monitorenter(枷锁)和monitorexit(释放锁)两个指令. monitorenter指令执行的时候会干什么呢? 每个对象都有一个关联的monitor,比如一个对象实例就有一个monitor…

volatile的作用及原理

前言 voliate关键字的两个作用: 1、 保证变量的可见性:当一个被volatile关键字修饰的变量被一个线程修改的时候,其他线程可以立刻得到修改之后的结果。当一个线程向被volatile关键字修饰的变量写入数据的时候,虚拟机会强制它被值刷…

voliate和synchronized

线程安全考虑三个方面:原子性,可见性,有序性 为什么使用voliate关键字? 正常情况下编译器为了加快程序运行的速度,对一些变量的写操作会先在寄存器或者是CPU缓存上进行,最后才写入内存.而在这个过程,变量的新值对其他线程是不可…

关于voliate关键字

现象 private static boolean is false;public static void main(String[] args) {new Thread(new Runnable() {Overridepublic void run() {System.out.println("thread 1 start");while (!is) {}System.out.println("thread 1 end");}}).start();try {T…

并发专题之---Voliate引发的各种原理问题

文章目录 前言JMMvoliate不保证原子性不保证原子性的解释AtomicInteger解决不保证原子性的问题为什么AtomicInteger可以解决原子性问题?CASCAS的内部原理CAS的缺点ABA问题原子引用解决ABA问题 禁止指令重排多线程环境下单例模式出现的问题双端检索机制解决办法双端检索机制的隐…

voliate类型的原理及用法

voliate类型,机器才读取执行代码读取内存后,将读取的内容存到高速缓冲区里,在硬件里是寄存器,这样在一下次读取的时候就可以直接从高速缓存区里面读取(cache),这也是读取速度加快的原因,但是如果…

voliate(轻量级的同步机制)

voliate特点: JMM内存模型三大特性:可见性,原子性,有序性。 1.禁止指令重排序: voliate实现禁止指令重排,避免多线程环境下程序出现乱序执行的现象。 多线程环境中线程交替执行,由于编译器优化重排的…

voliate工作实际应用场景

哈喽大家好,我是IT老哥,今天我们来讲讲面试必问的voliate 单线程的情况下呢,我们肯定用不到这个voliate 只有在多线程的情景下才能用到,文章结尾我会举一个经典的案例 voliate三特性 保证可见性;不保证复合操作的原子性…

voliate原理

voliate原理 voliate 当使用voliate关键字修饰共享变量(实例变量、静态变量)时,它将具备两个特性:可见性和禁止指令重排序优化 1.可见性 变量被修改后,会立即保存在主存中,并清除工作内存中的值。新值对于线程来说都是可见的…

C语言关键字之voliate

C语言关键字之voliate voliate的作用是作为指令关键字,确保本条指令不会因为编译器的优化而省略,而且要求每次从内存中直接读取值 当使用voliate 声明变量值时,系统总是重新从它所在的内存读取数据,直接访问变量地址&#xff0c…

java中voliate的讲解

Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在Java 5之后,volatile关键字才得以重…