文件操作杂记
在linux 学习中,文件操作是一个十分重要的模块.
通常, 我们使用open()来打开文件. 其实在open()的背后, 有好多有(fu)趣(za)的事情发生.
open()函数背后的系统调用相当复杂, 文章下面有链接, 可以详细理解.
我们主要来讲一下文件描述符和文件之间不可描述的关系.
进程级别的文件描述符表
系统级别的打开文件表
硬件级别的文件系统
硬链接和软链接
进程级别的文件描述符表
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。
—-维基百科
文件描述符对于我们而言, 十分熟悉. open函数的返回值即文件描述符, 在linux中, 每个进程都有一个文件描述符表, 里面每一个值都对应着等会要讲到的打开文件表的一项.
系统级别的打开文件表
内核为所有打开文件位置一张文件表, 每个文件表包含:
a. 文件状态标志(读、写、添写等)
b. 当前文件偏移量
c. 指向该文件v节点表项的指针(linux 没有使用v-node, 而使用了i-node)
—- 《APUE》
在内核中, 所有打开的文件都在一张表中, 由内核进行维护. 进程打开的文件描述符表中有一项file ptr, 这一项就是指向打开文件表的. 而打开文件表里存放着许多信息, 并且所有进程指向一个打开文件表, 这也就意味着当前文件偏移量等信息是同步的。 如果两个进程同时操作同一文件, 可能会出现竞争的情况, 所以要考虑给文件控制权上锁, 以形成原子操作。
上文提到不同进程的文件描述符可以指向同一个文件, 其实不同文件描述符也是可以指向同一文件的。 要实现不同文件描述符指向同一文件, 我们需要使用dup, dup2等函数。
下图描述了不同进程指向同一个打开文件表
硬件级别的文件系统
我们可以把一个磁盘分成一个或多个分区, 每个分区都可以包含一个文件系统, i 节点固定长度的记录项, 它包含有关文件的大部分信息, 如果观察一个柱面组的i节点 和 数据块部分, 则可以看到图4-14中所示的情况
—-《APUE》
柱面组上的目录块里面包含了文件的inode编号和文件名, inode节点指向数据块。 这就是linux文件系统的经典格式。 如果一个数据块不够存放文件的话, inode会指向多个数据块。 也是因为这种设计, 所以linux可能会出现 空余空间很大, 但是无法新建文件的问题。
硬链接和软链接
基于有些需要, Linux也支持链接文件. 在Linux中,有两种链接方式: 硬链接 和 软链接
硬链接
硬链接是在物理层面的链接, 命令为 ln oldname newname . 它会创建一个新的文件, 使它的inode节点也指向旧的文件数据块, 这样的话, 同一块数据块就有两个链接数了, 这也是stat中st_nlinks的数量, 当一个数据块有一个或一个以上的链接数的话, 它在逻辑上是存在的, 如果链接数为零的话,那么系统就会回收这块空间。软链接
软连接的命令是 ln -s oldfile newfile , 它会创建一个真实存在的文件, 具有自己的inode, 它里面保存着目标文件的绝对路路径。
区别
如果两个文件为硬链接关系的话, 如果原文件删除, 则另一个文件仍能访问数据, 只是inode的链接数减一。 口 .. 口
如果两个文件为软链接关系的话, 如果源文件删除, 则另一个文件不能访问数据
硬链接不能跨磁盘, 而软连接可以