Linux之文件系统

项目中出现了文件系统损坏的问题,所以找了些资料看了看,总结如下:

在Linux中,任何东西都被看做是文件。

文件描述符、文件节点(inode)、dentry cache


从上图可以看到,每个进程拥有一个文件描述表(files_struct),每个表项实际上是一个file结构体。图中每个表项指向一个file结构体,不过也可以利用dup2让多个表项指向同一个file结构体。


file结构体记录着一些文件操作信息:打开模式f_flags、当前读写位置f_pos、被引用的次数f_count、文件操作函数表(f_op)、文件目录项(f_dentry)。其中:

f_op是一个file_operations数据结构,都是一些文件操作函数,这个学过Linux驱动都熟悉

f_dentry包含目录项信息。图中”/home/akaedu/a"文件需要首先找到/home/目录,再找到akaedu目录后才能找到a文件。这些信息都保存在dentry中。实际上,这些文件和目录的信息都保存在文件节点中。 当然为了加快访问文件和目录速度,内核会缓存最近访问的目录项信息(dentry cache)。

找到了文件实际上就是在dentry中找到对应的文件节点。节点使用inode结构体表示,它保存着一些信息:用户id(i_uid), 文件大小(i_size)、权限(i_mode)、节点操作函数表(i_op)、超级块信息(i_sb)。其中i_op和file_operations类似,不过节点操作函数表都是一些建立硬连接、删建目录等操作函数。超级块实际上是从磁盘的MBR扇区中读到的数据,它包含了当前分区文件系统类型,块大小,以及当前分区挂载的路径(例如图中挂载在/home目录上)


因此,当打开一个文件时,首先在dentry中进行查找(dentry信息也是从磁盘中读取到的,不过内核会做一些缓存)。找到文件节点意味着找到文件,从磁盘中读取节点文件(若缓存了,直接从dentry中读取)。解析节点信息,例如用户id和权限等。一旦成功,在file_struct中分配可用文件描述符,建立file数据结构并赋值f_dentry,f_op,清零f_pos,增加应用f_count。

top命令输出能够看到cache的适用


文件读和写

一个文件系统一般分为3个区:节点区、超级块、数据区。一个节点代表着一个文件,节点中带有文件的一些信息(例如大小、时间等),同时也保存着文件数据存放的位置。对于文件数据的读写涉及到几个缓存:应用缓存、页缓存、磁盘缓存。

Linux对文件操作提供了两种操作方式:

open、close、read、write。定义在unistd.h

fopen、fclose、fread、fwrite。定义在stdio.h

区别是stdio.h是C语言标准库提供的定义在libc中,unistd.h则是Linux系统头文件,说明是系统调用接口。


先看看写操作write和fwrite的区别:

write一般将数据写入page cache中(当然也可以使用mmap将内核空间直接映射到用户空间,可以解决read write带来的用户态/内核态切换的开销)

fwrite会讲数据先写入clib buffer中(可以再调用fflush将数据搬移到page cache中),待fclose时再讲数据拷贝到page cache中。


上图中可以看到,数据写入到磁盘之前经过许多层。实际上,write是一个异步的过程,数据被拷贝到page cache后write函数就立刻返回。至于什么时候数据能够被写入到磁盘中,write函数并不关心(一般情况,内核中守护进程flushd会检查所有page是否dirty,若dirty则说明有数据被写入,这个守护进程会将page cache中的数据刷新到磁盘中的)

上述过程这样做的目的是为了提高系统的响应速度,却带来了数据不一致的问题(例如当守护进程还没来得及刷新数据时,系统崩溃了)。因此,有时候我们需要将数据直接写入到磁盘中,可以给open函数传入O_DIRECT参数。或者使用O_SYNC,这样write必须等到数据刷新到磁盘后才能返回。

对于write还需要注意当写数据大小小雨PIPE_BUF(4096)时,写操作是原子的。(这意味着两个进程分别写入AAA和BBB,文件中不会出现ABABAB)

读操作则没有这么复杂,因为它是同步的。这意味着,每次读取数据必须要读到磁盘中的数据(当然内核中也可以进行缓存,但磁盘和读取到的数据总是一致的)。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值