转:《http://linuxperf.com/?p=153》

一、概述

  文件系统要解决的一个关键问题是怎样防止掉电或系统崩溃造成数据损坏,在此类意外事件中,导致文件系统损坏的根本原因在于写文件不是原子操作,因为写文件涉及的不仅仅是用户数据,还涉及元数据(metadata)包括 Superblock、inode bitmap、inode、data block bitmap等,所以写操作无法一步完成,如果其中任何一个步骤被打断,就会造成数据的不一致或损坏。举一个简化的例子,我们对一个文件进行写操作,要涉及以下步骤:

  • 从data block bitmap中分配一个数据块;
  • 在inode中添加指向数据块的指针;
  • 把用户数据写入数据块。
  1. 如果步骤2完成了,3未完成,结果是数据损坏,因为该文件认为数据块是自己的,但里面的数据其实是垃圾;
  2. 如果步骤2完成了,1未完成,结果是元数据不一致,因为该文件已经把数据块据为己有,然而文件系统却还认为该数据块未分配、随后又可能会把该数据块分配给别的文件、造成数据覆盖;
  3. 如果步骤1完成了、2未完成,结果就是文件系统分配了一个数据块,但是没有任何文件用到这个数据块,造成空间浪费;
  4. 如果步骤3完成了,2未完成,结果就是用户数据写入了硬盘数据块中,但白写了,因为文件不知道这个数据块是自己的。

二、应对之策

  日志文件系统(Journal File System)就是为解决上述问题而诞生的。它的原理是在进行写操作之前,把即将进行的各个步骤(称为transaction)事先记录下来,保存在文件系统上单独开辟的一块空间上,这就是所谓的日志(journal),也被称为write-ahead logging,日志保存成功之后才进行真正的写操作、把文件系统的元数据和用户数据写进硬盘(称为checkpoint),这样万一写操作的过程中掉电,下次挂载文件系统之前把保存好的日志重新执行一遍就行了(术语叫做replay),避免了前述的数据损坏场景。

  有人问如果保存日志的过程中掉电怎么办?最初始的想法是把一条日志的数据一次性写入硬盘,相当于一个原子操作,然而这并不可行,因为硬盘通常以512字节为单位进行操作,日志数据一超过512字节就不可能一次性写入了。所以实际上是这么做的:给每一条日志设置一个结束符,只有在日志写入成功之后才写结束符,如果一条日志没有对应的结束符就会被视为无效日志,直接丢弃,这样就保证了日志里的数据是完整的;

  一条日志在它对应的写操作完成之后就没用了,占用的硬盘空间就可以释放。保存日志的硬盘空间大小是有限的,被循环使用,所以日志也被称为circular log。

至此可以总结一下日志文件系统的工作步骤了:

  • Journal write : 把transaction写入日志中;
  • Journal commit : 在一条日志保存好之后,写入结束符;
  • Checkpoint : 进行真正的写操作,把元数据(metadata)和用户数据(user data)写入文件系统;
  • Free : 回收日志占用的硬盘空间。

效率问题:

  以上方式把用户数据(user data)也记录在日志中,称为Data Journaling,Linux EXT3文件系统就支持这种方式,这种方式存在效率问题:就是每一个写操作涉及的元数据(metadata)和用户数据(user data)实际上都要在硬盘上写两次,一次写在日志里,一次写在文件系统上。元数据倒也罢了,用户数据通常比较大,拷贝几个GB的电影文件也要乘以2实在是降低了效率。

  一个更高效的方式是Metadata Journaling,不把用户数据(user data)记录在日志中,它防止数据损坏的方法是先写入用户数据(user data)、再写日志,即在上述”Journal write”之前先写用户数据,这样就保证了只要日志是有效的,那么它对应的用户数据也是有效的,一旦发生掉电故障,最坏的结果也就是最后一条日志没记完,那么对应的用户数据也会丢,效果与Data Journaling丢弃日志一样,重要的是文件系统的一致性和完整性是有保证的。Metadata Journaling又叫Ordered Journaling,大多数文件系统都采用这种方式。像Linux EXT3文件系统也是可以选择Data Journaling还是Ordered Journaling的。

linux 文件系统工作原理的更多相关文章

  1. Linux Kbuild工作原理分析(以DVSDK生成PowerVR显卡内核模块为例)

    一.引文 前篇博文<Makefile之Linux内核模块的Makefile写法分析>,介绍了Linux编译生成内核驱动模块的Makefile的写法,但最近在DVSDK下使用Linux2.6 ...

  2. linux文件系统实现原理简述【转】

    本文转载自:https://blog.csdn.net/eleven_xiy/article/details/71249365 [摘要] [背景] [正文] [总结]   注意:请使用谷歌浏览器阅读( ...

  3. Linux keepalived工作原理

    keepalived简介与工作原理 Keepalived的作用是检测服务器的状态,如果有一台web服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他 ...

  4. linux文件系统底层原理

    Linux文件系统中的文件是数据的集合,文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux 用户和程序看到的文件.目录.软连接及文件保护信息等都存储在其中. 底层原理图: 在讲解各个 ...

  5. Linux workqueue工作原理 【转】

    转自:http://blog.chinaunix.net/uid-21977330-id-3754719.html 转自:http://bgutech.blog.163.com/blog/static ...

  6. Linux Shell 工作原理

    Linux系统提供给用户的最重要的系统程序是Shell命令语言解释程序.它不属于内核部分,而是在核心之外,以用户态方式运行.其基本功能是解释并执行用户打入的各种命令,实现用户与Linux核心的接口.系 ...

  7. Linux AWK工作原理

    本篇文章我们主要为大家介绍 AWK 是如何工作的. AWK 工作流程可分为三个部分:1.读输入文件之前执行的代码段(由BEGIN关键字标识).2.主循环执行输入文件的代码段.3. 读输入文件之后的代码 ...

  8. Linux系统开机启动时的工作原理

    Linux系统开机启动时的工作原理也是深入了解Linux系统核心工作原理的一个很好的途径. 启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至 ...

  9. 【转】Linux Page Cache的工作原理

    1 .前言 自从诞生以来,Linux 就被不断完善和普及,目前它已经成为主流通用操作系统之一,使用得非常广泛,它与Windows.UNIX 一起占据了操作系统领域几乎所有的市场份额.特别是在高性能计算 ...

随机推荐

  1. linux命令学习——ps

    1.命令简介 ps命令用来查看系统上的进程信息.要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而 ps 命令就是最基本同时也是非常强大的进程查看命令.使用该命令可以确定 ...

  2. Concurrent HTTP connections in Node.js

    原文: https://fullstack-developer.academy/concurrent-http-connections-in-node-js/ -------------------- ...

  3. free的说明

    http://www.cnblogs.com/peida/archive/2012/12/25/2831814.html

  4. Python在VSCode中进入交互界面调试

    VSCode非常强大,断点好用,美中不足,每次只能通过下面窄窄一行进行各种检查,而python的优点就在于交互式的调试,所以希望能够在断点时能够进入到正常的交互界面进行调试. 我用的插件是: 设置交互 ...

  5. VS2017专业版使用最新版Qt5.9.2教程

    VS2017专业版使用最新版Qt5.9.2教程(最新教材) 最近三天一直在安装Qt5.9.2,为了能够在自己专业版的VS2017上面使用?可以算是花费了不少的功夫.但是一路上并不是很顺利,就在刚才,终 ...

  6. 【Nodejs】外研社小学英语教材一年级起各年级英语音频下载(全)

    两个爬虫合作成的,放在这里分享给有需要的人. 下载地址:https://pan.baidu.com/s/19hJ59SsX9uTfFtBxaRxJ8A 2018年5月10日

  7. RibbonControl中的主题设计

    Ribbon+扁平化 据调查,其实人们可能最多只用到全部 Office 功能的 5%,为此,微软交互式团队推出了Ribbon风格,一时间,很多软件升级后都换成了Ribbon界面:扁平化其实不是新东西, ...

  8. Android中创建option menu

    1.首先在res目录下新建一个menu文件夹,右击res目录->New->Directory,输入文件夹名menu,点击OK. 接着在这个文件夹下再新建一个名叫main的菜单文件,右击me ...

  9. jQuery开发技巧

    jQuery 事件 - submit() 方法 $("form").submit(function(e){}); 当提交表单时,会发生 submit 事件. 该事件只适用于表单元素 ...

  10. javascript链式语法

    因为 jQuery 库的缘故,链式语法在前端界变得非常流行.实际上这是一种非常容易实现的模式.基本上,你只需要让每个函数返回 'this',这样其他函数就可以立即被调用.看看下面的例子. var bi ...