Linux文件操作解析
来源:互联网 发布:dracut命令安装linux 编辑:程序博客网 时间:2024/06/06 03:47
最近重读APUE,之前很多一知半解的概念变得清晰了许多。其中就有关于Linux文件操作的一些系列api及其背后的概念。刚好就在博客里总结一下。
本文仅针对一般文件的操作,由于Linux“一切皆文件”的设计哲学,如果要谈广义上的文件操作,那么socket编程相关的内容也要牵扯进来了。
首先,Linux对进程提供文件描述符(file descriptor,以下简称fd)作为所有文件的身份标示。对于每个进程而言,在进程用户空间维护一张文件描述符表。表的每一行包含两项--文件描述符及文件指针。文件指针指向打开文件表(open file table)的一行.打开文件表是一张系统级的表。每一行包括了文件偏移量,文件状态(status flag),以及一个指向inode表项的指针,inode表同样是一张系统级的表,它储存了真正的被打开文件的文件信息,文件锁等数据,其每一项与实际打开文件是一对一的关系。
打开文件表和实际打开文件的关系是多对一的关系。这是由于同一个文件会被以不同的形式(r/w/rw)打开多次,也会被多个进程打开多次。每一次open操作都会创建一个文件描述符表项和打开文件表项。同时,由于子进程对父进程文件表的继承,以及dup操作导致的文件别名现象,文件描述符项与打开文件表项也是多对一关系。
文件描述符表,打开文件表,inode表关系如下图所示
针对文件和fd,Linux提供一套统一的api操作接口。分别为:文件打开及创建(create(..)已过时):open(...),文件关闭:close(...),文件偏移量设置:lseek(...),写文件:write(...),读文件:read(...).(具体函数参数和flag宏请自行查阅)。这五大函数在被调用时都会直接触发sys_call导致程序陷入内核,由此引发的context switch不可避免地会造成性能开销。在陷入内核后,write()和read()函数并不一定会直接于磁盘交互。Linux kernel 设置了内核缓冲区以减少I/O操作。对使用者,Linux提供了至少四种方式来帮助我们控制内核缓冲区的行为。
1.open(...)函数的O_SYNC标志,用该标志打开的文件在进行write操作时会阻塞至物理I/O操作完成为止。即保证本次写操作是写入磁盘的。
2.void sync()函数:将所有被修改过的块缓冲区排入写队列等待内核进行物理I/O操作同步,然后返回,update守护进程会定时调用该函数,从而保证缓冲区和磁盘数据的一致性。
3.int fsync(int fd)函数:仅对指定fd对应的文件有效,但会等到写磁盘结束后再返回。
4.int fdatasync(int fd)函数:同fsync,但不会更新文件属性。
以上介绍了直接依据fd进行的文件操作,在上文中也提到,这些基于fd的函数会直接触发sys_call,而sys_call是有性能开销的,参照内核缓冲区的设计思想,既然文件的读写与文件的实际内容未必要是时时刻刻都同步的,为什么不能在用户态设置一个缓冲区,从而减少sys_call的发生的?
本着这一原则,Linux提供基于流的拥有用户空间缓存的文件操作api。这一套API不再用fd作为文件标识,而是使用FILE结构体。程序中预定义的三个文件指针stdout,stdin和stderr便是基于FILE结构体的指针。我们常用的printf函数便是一个针对stdout的操作。FILE对应的文件缓冲区有三种文件缓冲模式:
1.全缓冲:顾名思义,仅在缓冲区满时进行sys_call同步数据,流被打开时的默认缓冲方式。
2.行缓冲:只有遇到换行符或缓冲区满时执行I/O操作(还有一种情况是当流被用作输入时,其输出缓冲会被冲洗)。通常涉及终端的流使用此缓冲方式,如stdout,stdin。
3.不缓冲:相当于没有用户空间缓冲区。stderr用此缓冲方式以及时打印错误信息。
另:
Linux同样提供一系列函数来控制缓冲区的属性及行为:
1.fflush(...):冲洗缓冲区,强制I/O操作。
2.setbuf与setvbuf:两者都可以设置特定流的缓冲区大小,后者可以设置缓冲方式。
至此,我们可以发现,如果使用基于流的文件读写api,整个文件读写过程大致如下图所示:
最后简单列出基于流的文件操作api:
打开文件:fopen(标准打开函数),fdopen(将fd结合到一个新流,用于包裹无法被fopen打开的文件,如socket),freopen(将打开文件定向到已有流)
关闭文件:fclose(文件关闭时,输出缓冲被冲洗,输入缓冲被丢弃)。
读写类函数太多,在此不一一列出。
- Linux文件操作解析
- linux网卡配置修改IP地址操作及文件解析
- 解析linux 文件和目录操作的相关函数
- 解析linux 文件和目录操作的相关函数
- Linux常用命令解析(三)--文件操作命令(上)
- 异常操作(解析文件)
- linux用户文件解析
- 解析Linux特殊文件
- linux根文件解析
- 解析Linux特殊文件
- linux /proc 文件解析
- Linux 文件权限解析
- Linux profile文件解析
- linux 文件权限解析
- linux常用文件解析
- Linux文件目录解析
- dom解析XML文件操作
- VC++文件操作函数解析
- Android学习-常见的UI控件 监听按钮的点击事件
- SpringMVC--RequestContextListener
- HDU 4778 Gems Fight! 【记忆化搜索+位操作】
- POJ 2976 Dropping tests 01分数规划Dinkelbach算法
- 流程图
- Linux文件操作解析
- [JavaScript][AJAX]封装好的AJAX工具类
- DES代码讲解
- Java 应用发布后,需要关注的7个性能指标
- gcc工作流程
- RaspberryPi树莓派远程文件管理
- 日志(一)
- 51单片机外设之——按键的检测(快速识别)
- Java程序性能优化——性能指标