前文中我们已经分析了文件系统,而文件系统的精髓所在是让用户可以通过文件描述符来对指定的inode进行一系列的操作。本章开始学习伪文件系统,伪文件系统和普通文件系统的区别在于,其inode对用户不可访问,即仅在内核态可见,从用户层的视角来看该文件系统并不存在。伪文件系统的作用是对一些操作系统中的元素进行封装,和普通的文件统一接口,如块设备bdevfs,管道文件pipefs,套接字socketfs等。通过这种方式的统一封装,才实现了Linux一切皆文件的思想。如下图中红色的都应该算是伪文件系统,本章就学习其中的procfs/sysfs/pipefs。1proc文件系统1.1数据结构proc文件系统
学习完了fuse的内核实现,我们真实的来看怎么实现一个简单的fuse文件系统,我们还是以之前的例子,对于用户空间需要实现基于libfuse实现的应用程序hello,例子可以参考http://fuse.sourceforge.net/helloworld.html首先,我们需要编译libfuse,其可以参考下面的github,里面有编译的相关方法1libfuse库测试libfuse的仓库地址为:https://github.com/libfuse/libfuse使用其方法编译安装完成如下图所示,表示libfuse库已经安装到我们的系统中libfuse提供了两个APIs:一个“high-level
前面我们学习了VFS的框架,VFS被夹在两层之间:上层和下层。上层是系统调用层,在这个层中,用户空间进程进入内核请求服务(这通常通过libc包装器函数完成),较低的一层是一组函数指针,每个文件系统实现一组,当VFS需要执行需要特定文件系统特定信息的操作时,它会调用该操作。VFS最重要的对象filesystemtypes:文件系统类型superblock:整个文件系统的元信息inode:单个文件的元信息dentry:目录项,一个文件目录对应一个dentryfile:进程打开的一个文件如上图,VFS后的文件系统实现具体有以下几种基于块设备的文件系统(Block-basedFS):ext2-4,bt
文件系统管理一组数据结构以实现预期的抽象:文件,目录,以及所有其他的元数据,以满足我们期望的从文件系统获得的基本抽象。文件系统必须持久化,存储在断电也能保留数据的设备上。所以文件系统面临了一个主要的挑战在于,如何在断电或者系统崩溃的情况下,更新持久化数据。如果在更新磁盘结构的过程中,机器断电,会发生什么?操作系统遇到错误并崩溃,会发生什么?本章中,我们详细探讨这个问题,看看文件系统克服它的一些方法1背景我们假定磁盘上使用一个标准的简单的文件系统结构,类似于我们之前分析的文件系统,如下图所示一个inode位图(inodebitmap只有8位,每个Inode一个)一个数据位图(databitmap
对于Linux延续着Unix的一个哲学思想:一切皆文件,应用看到的所有对象都是文件。应用程序通过系统调用陷入内核中,访问内核的资源,VFS作为通用文件系统接口,通过各种不同文件系统的实现,主要是以块设备为基础的物理文件系统,例如EXT2/EXT3等,对于VFS层通过不断的演变支持了更多的文件系统,其主要是中间层,对上提供POSIXAPI,对下对接不同的文件系统驱动向上主要是提供file_operations抽象接口,包括文件的打开,读写,mmap映射,ioctl等,用户空间无须考虑具体的文件系统和实际的存储介质。向下则要兼容个各种不同的文件系统如果想要自己实现一个文件系统的话只要实现一个满足V
原文:AnIntroductiontoLinux’sEXT4Filesystem链接:https://opensource.com/article/17/5/introduction-ext4-filesystem本文的目的是仔细阅读EXT4的历史记录,功能和最佳使用,并了解其与Ext文件系统的先前迭代的不同之处。在先前关于Linux文件系统的文章中,我写了一份说明书去介绍Linux文件系统,里面有一些高级的概念,比如说,一切都是文件。我很想去深入地讨论更多EXT文件系统的特性的信息。所以,首先让我们来回答这个问题:什么是文件系统?一个文件系统应该遵循以下特点:Datastorage:任何文件
学习文件系统,我们的目标是如何实现一个简单的文件系统?磁盘上需要什么结构?它们需要记录什么?如何访问?对于这些问题,我们就需要理解文件系统的基本工作原理,可以从以下两个方面着手文件系统的数据结构:文件系统在磁盘上使用哪些类型的结构来组织其数据和元数据?当一个进程打开一个文件时,会发生什么?在读取或写期间会访问哪些磁盘结构?访问方法:如何将进程发出的调用,如open()/write()/read()等,映射到它的结构上?在执行特定系统调用期间读取哪些结构本章就基于以上的目的,主要学习访问过程中发生具体的细节1数据结构首先,我们通过进程task_struct结构体中fs成员表示了进程可见根文件系统
前一章学习了虚拟文件系统组成的超级块、索引节点、目录项、文件四个结构体对象,那么就开始看内核是如何建立挂载点目录项与挂载文件系统的?我们接着下面图,学习整个mount的过程。1数据结构虚拟文件系统通过目录项dentry实例组成的跟文件系统管理内核所有的文件,具体文件系统根目录需要关联到内核跟文件系统中某一目录项**(挂载点)**才能接入跟文件系统,如下图所示将磁盘分区sda1的文件系统根目录与跟文件系统中的/mnt目录项建立关联,称之为挂载,/mnt目录项称之为挂载点根文件系统中的挂载点可以同时挂载多个文件系统,sda2在da1分区之后挂载,则分区sda2文件系统可见,分区sda1被引藏,当分
最近一直忙于基于android的动态分区的方案和virtualA/B方案通过rust重写升级的框架,里面有将IO子系统的框架学习了,主要是基于deviceMapper的用法和实现原理,只是学习了基本的原理和如何使用,对于其最底下的IO层基本不知道如何实现,准备放到文件IO章节学习。本周末接着学习文件系统,之前了解了以下文件系统的基本知识,本次开始真正进入到内核的虚拟文件系统学习之旅。1VFS架构我们从一个简单的问题开始,我们如何访问文件?作为一个普通的使用者,我们不太关系我们如何访问计算机上的数据,不管这个数据是存储在机械硬盘上,还是SSD,甚至是远程的设备上;其次,我们也不想关心,我们现在用
当Unix操作系统首次引入时,使用了minix文件系统,它非常简单,基本上,它的数据结构在磁盘上看起来像是这样:超级块包括了有关整个文件系统的信息,卷大小,有多少inode,有多少空闲块等等,磁盘的inode区域包括文件系统的所有inode,最后,大部分磁盘都被整个数据块占用。对于非常常见的读操作,每当第一次读取inode,然后读取文件的数据块时,就会导致寻道时间很长更糟糕的是,文件系统最终会变得非常的碎片化,该设计没有对空闲空间的管理,结果导致在磁盘上来回访问逻辑上连续的文件,从而大大的降低了性能例如,假设一下数据块区域包括4个文件(A/B/C/D),每个文件大小为2个块:如果删去B和D,则
文件系统(三)—老祖宗长的什么样文件系统已经发展的如此完善,同时文件系统的代码也越来越复杂,我们通过前面两章大致知道了可以如何去设计一个文件系统,所以我们有必要去了解一下linux文件系统的老祖宗长的什么样。一方面,我们可以通过这个可以了解文件系统最初的样子,更加加深的理解文件系统的理念和基础概念;另外一方面是现代的文件系统都比较庞大,不容易理解,而老的文件系统才几千行代码,理解起来比较容易。1minix文件系统当编写原始Linux内核,LinusTorvalds需要一个文件系统,但是不想开发它。因此他简单的使用了Minix文件系统,这是AndrewS.Tanenbaum开发的,而且是Tane
前面一章主要学习了文件系统的存储和分配方式的理论知识,本章接着理论知识,如何设计一个文件系统(本章不涉及任何代码实现),其主要的内容包括如下:如何一步步设计一个文件系统,了解文件系统由那些组成当我们读写文件时底层的工作原理是什么,从组成到实现原理1.文件系统的组成部分对于文件系统我们只需要支持两种最基本的操作:读和写,就可以解决长期的存储问题。不过,这里存在很多不便于实现的操作,特别是有很多程序或者多用户使用着的大型系统上,很容易产生一些问题,例如:如何找到对应的信息?如何防止一个用户读取/写入另外一个用户的数据?如何直到哪些块是空闲的?对于用户关心的是文件是怎么命名的,可以进行哪些操作,目录
前面主要是学习linux进程管理的调度,其细节越来越多,结合目前移动设备,其调度算法越来越复杂,涉及到芯片涉及,电源管理,多核负载等,这块内容暂时告一段落,本章正式进入到文件系统的学习。到目前为止,我们看到了两项关键操作系统的发展:进程,是虚拟化CPU地址空间,是虚拟化的内存在这两种抽象的共同作用下,程序运行时就好像它在自己的私有的独立世界中一样,好像它有自己的处理器(或多处理器),好像它有自己的内存空间,这种假象使得对系统的编程变得越来越容易,在这一部分中,我们还需要加一个持久存储。现在的磁盘是具有大容量、低成本以及持久化的特点,即使发生断电、磁盘上的数据也不会丢失。但是对于一般用户而言,磁