本文由作者周梁伟授权网易云社区发布。

近日做的项目中涉及到多进程共同读写多个文件的问题,文件名和最后修改时间都是可能会被频繁修改的,因而识别文件的唯一性会产生相当的麻烦,于是专门再学习了一下文件系统对文件的组织管理方式。

一、    文件在文件系统中的组织方式

一块物理磁盘可以被分为若干个分区,分区的初始化操作就是在上面建立文件系统,如ext3,ext4,ntfs或fat32等都是文件系统的概念,还有网络文件系统如NFS等。同块磁盘上的不同分区也可以被指定不同的文件系统,文件系统对文件在磁盘上的数据读写方式做了抽象。一个文件系统中又被分为多个卷(Cylinder Group),每个卷中最主要的部分是inode基路段和数据块段。i-node结构唯一指定了一个文件实例,这个数据结构中包括了inode编号,所有包含的数据块的信息和该inode被引用的计数等。可以这么认为,要唯一识别的一个磁盘上的文件,只需要获得inode-number就可以了。文件或者目录则是存放在数据块中directory block,其中包含了文件名和实体文件的inode-number等信息。文件名是可以随时被改变的,只要其中的inode-number没有发生改变,则指向的就是同一个文件。所以在应用程序中要判断文件是否相同如果依靠filename是不可靠的,只有获取到文件的inode-number才是可靠的。如在log4j这种日志应用中,日志文件的归档方式会使文件名不断发生变化,当前你less到的app.log在下一分钟可能就变成了app.log.1。在这种场景下,程序只能通过获取文件inode-number来识别文件。

二、    文件操作

前面说了文件在磁盘上的存放是以inode-number为唯一id来区分的,在进程打开一个文件读写时,操作系统又会为文件分配一个"指针"来访问文件,而不是直接使用inode-number。这个指针就是FileDescriptor(下面简称FD),FD是一个动态的概念,是进程中调用create后open文件操作是返回的一个Long值,当文件关闭时这个FD也就失效了,所以同一个文件如果被打开两次获取到的FD会是不同的。进程打开文件的情况如下图所示,在进程中维护了一张表记录所有打开的文件,每一条记录表示一个FileDescriptor,每个进程在开始时都默认打开了三个文件,FileDescriptor分别是0,1,2,既stdin, stdout和stderr。FD记录中包含了一张FileTable,记录了文件的状态信息,offset和V-node指针,V-Node指针才真正指向了磁盘上的文件实体。(这里的V-Node是在inode之上抽象出来的概念,因为i-node在不同的文件系统中会有实现上的差异,V-Node是为了统一不同文件系统的接口抽象出来的一层,在Linux中V-Node被称为 FileSystem independent INode ,而INode 称为FileSystem dependent Inode,我们可以简单的理解为 V-Node就是INode)。

当一个文件被多个进程共享读写时,可以看如下图:

这里进程A的fd3和进程B的fd4其实指向的是同一个实体文件,但是这两个进程维护了两张不同的文件表,维护了不同的offset位置。所以如果进程不是采用append方式写文件,两个进程写入的内容可能出现相互覆盖。这里也可能看到虽然FD不同,但是可以指向同一个实体文件,也说明了用FD来判断文件唯一性是不靠谱的。
关于FD和INode,还有关于缓存的重要注意事项。
由于操作系统在接收到文件写请求时可能将写入内容放到缓存中,所以提供了flush和sync等操作来将缓存中的内容强制刷入磁盘。但是这两个操作作用是不同的。
flush会将数据刷入到FileDescriptor中,但是不会刷入Inode
sync/fsync/fdatasync则会强制将FD中的数据刷入Inode中。

三、    Java操作文件的接口

最后需要注意的一点是,虽然在文件的存续期间,inode可以认为是识别该文件的唯一标识,但是文件系统对inode有回收重用的机制,在文件被删除之后,原来的inode可以被分配给新创建的文件,这种情况下,如果一味以inode相同来判定新旧文件是不是同一个文件可能会出现错误;应对这种情况确实也没有更好的办法,一种解决方法是,提取文件中部分内容的MD5或SHA-1这种指纹信息作为标识,以inode+md5是否相同来决定是否是同个文件。

免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请访问网易云社区

相关文章:
【推荐】 初步探索前端性能测试
【推荐】 四步详解数据分析套路
【推荐】 逻辑编程入门--clojure.core.logic

关于文件的INode与Java中的文件操作接口的更多相关文章

  1. Java中删除文件、删除目录及目录下所有文件(转)

    原文链接:Java中删除文件.删除目录及目录下所有文件 知识点:File.delete()用于删除“某个文件或者空目录”!所以要删除某个目录及其中的所有文件和子目录,要进行递归删除,具体代码示例如下: ...

  2. Java中的文件操作

    在使用计算机编程中,常常会用到对于文件的操作,以下是我对于Java中文件的相关内容学习之后的一个总结和在学习过程中遇到的一些问题. 一.什么是文件 对于文件进行操作,首先我们要知道什么是文件.在此之前 ...

  3. Java中读取文件

    Java中读取文件,去除一些分隔符,保存在多维数组里面 public void readFile(String filePath) { File file=new File(filePath); Ar ...

  4. JAVA中获取文件MD5值的四种方法

    JAVA中获取文件MD5值的四种方法其实都很类似,因为核心都是通过JAVA自带的MessageDigest类来实现.获取文件MD5值主要分为三个步骤,第一步获取文件的byte信息,第二步通过Messa ...

  5. Java中获取文件路径

    Java中获取文件路径 1.实例说明 (1)得到 ClassPath的绝对URI路径 Thread.currentThread().getContextClassLoader().getResourc ...

  6. java中常量文件的配置与读取

    java中常量文件的配置与读取: package com.floor.shop.user.util; import java.io.InputStream; import java.io.InputS ...

  7. Java中的文件操作(一)RandomAccessFile

    今天,学到的是java中的文件操作. Java.IO.File Java中操作文件用到RandomAccessFile类,既可以读取文件内容,也可以向文件输出数据,但不同与普通输入/输出流的是Rand ...

  8. java中把文件拷贝到指定目录下最简单几种方法

    java中把文件拷贝到指定目录下最简单几种方法   String savePath = "D:/file";// 文件保存到d盘的file目录下 File savefile = n ...

  9. Java中移动文件或目录的方法盘点

    本文不再更新,可能存在内容过时的情况,实时更新请移步原文地址:Java中移动文件或目录的方法盘点: import org.apache.commons.io.FileUtils; import jav ...

随机推荐

  1. jquery获取当前屏幕宽度

    参考文章 <script type="text/javascript"> $(document).ready(function() { alert($(window). ...

  2. 实现Quartz的动态增删改查

    1. Maven依赖 <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId> ...

  3. Halcon的二维码解码步骤和解码技巧

    一.二维码简介 1 . 类型多样,常见的有QR Code二维码. Data Matrix二维码等. 2.高密度编码,信息容量大. 3.容错能力强,具有纠错功能:二维码因穿孔.污损等引起局部损坏时,照样 ...

  4. PAT 1065 单身狗(25)(STL-map+思路+测试点分析)

    1065 单身狗(25 分) "单身狗"是中文对于单身人士的一种爱称.本题请你从上万人的大型派对中找出落单的客人,以便给予特殊关爱. 输入格式: 输入第一行给出一个正整数 N(≤  ...

  5. hg 添加用户

    .hg目录下hgrc文件 [ui] username = lyd

  6. asio 广播代码示例

    代码网络收集 修改了一个编译的小问题 客户端 // Client.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include < ...

  7. a标签的四个伪类

    A标签的css样式   CSS为一些特殊效果准备了特定的工具,我们称之为“伪类”.其中有几项是我们经常用到的,下面我们就详细介绍一下经常用于定义链接样式的四个伪类,它们分别是: :link    :v ...

  8. 05 数据库入门学习-正则表达式、用户管理、pymysql模块

    一.正则表达式 正则表达式用于模糊查询,模糊查询已经讲过了 like 仅支持 % 和 _ 远没有正则表达式灵活当然绝大多数情况下 like足够使用 #语法 select *from table whe ...

  9. 2018.09.26 bzoj1015: [JSOI2008]星球大战starwar(并查集)

    传送门 并查集经典题目. 传统题都是把删边变成倒着加边,这道题是需要倒着加点. 处理方法是将每个点与其他点的边用一个vector存起来,加点时用并查集统计答案就行了. 代码: #include< ...

  10. 2018.07.03 BZOJ 1007: [HNOI2008]水平可见直线(简单计算几何)

    1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec Memory Limit: 162 MB Description 在xoy直角坐标平面上有n条直线L1,L2,-Ln, ...