欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

APUE 学习笔记 —— 文件I/O

程序员文章站 2023-01-29 15:07:35
本章节主要讲了 Linux 系统下的关于文件I/O操作的几个函数:open、read、write、lseek、close 的使用和需要注意的一些细节。接着,又介绍了多进程见如何共享文件。下面开始知识点梳理。 文件描述符 对于内核来说,所有打开的文件,都是通过文件描述符来引用。当打开或创建一个新的文件 ......

本章节主要讲了 linux 系统下的关于文件i/o操作的几个函数:open、read、write、lseek、close 的使用和需要注意的一些细节。接着,又介绍了多进程见如何共享文件。下面开始知识点梳理。

文件描述符

对于内核来说,所有打开的文件,都是通过文件描述符来引用。当打开或创建一个新的文件的时候,内核都会向进程返回该文件的文件描述符。文件描述符是什么,可以参考*——文件描述符。unix 系统按惯例,会将0与进程的标准输入关联,将1与进程的标准输出关联,将2与进程的标准错误关联。

open 与 openat 函数的使用

APUE 学习笔记 —— 文件I/O

  • oflag 参数:
    是通过在头文件 <fcntl.h> 中定义的常量中的一个或多个进行 “或”运算构成的。这里不再一一详述每个常量及其含义,感兴趣的小伙伴可以自行去查阅。
  • path 参数:
    是要打开和创建文件的名字。
  • fd 参数:
    fd 把open 和 openat 函数区分开来,具体有三种可能:
    1. 当path是绝对路径时, openat 就相当于是 open;
    2. path制定的是相对路径名称时,fd指出了相对路径名称的在文件系统中的开始位置;
    3. path是相对路径,fd参数具有特殊值 at_fdcwd。此时,路径名在当前工作目录中获取,openat 函数在操作上与 open 函数类似;
      本节还讲到了 tocttou 思想以及文件名与路径名被截断的问题。

creat 函数

APUE 学习笔记 —— 文件I/O
creat函数是以只写的形式来打开一个新的文件的。

close 函数

APUE 学习笔记 —— 文件I/O
关闭一个文件,会关闭该进程在当前文件上加的所有记录锁。一个进程结束之后,内核会自动关闭其打开的所有文件。

lseek 函数

APUE 学习笔记 —— 文件I/O
lseek 函数仅会将当前的文件偏移量记录到内核中,其不会引起任何 i/o 操作。该偏移量是用来进行下一次读或者写的游标。偏移量的大小可以与文件实际大小不对应。当大于文件当前的实际长度的时候,对该文件的下一次写将加长该文件,且会形成一个空洞。位于文件中但是没有写过的字节都读为0。具体什么是空洞,可以看下百科——文件空洞

read 函数

APUE 学习笔记 —— 文件I/O
如果 read 成功,则会返回读到的字节数。如果已经读到了文件的末尾,会返回0。

write 函数

APUE 学习笔记 —— 文件I/O
对于普通文件,通常从当前的偏移量开始;如果在打开文件的时候,指定了 o_append操作,则在每次写操作之前,将文件的偏移量设置在文件的末尾。每次写成功,文件的偏移量都会变化。

i/o 效率

大多数文件系统为改善性能,都会增加“预读”技术。当检测到正在进行顺序读取时,系统就试图读入比实际锁要求更多的数据。

文件共享

unix 系统支持不同进程之间共享打开文件。内核使用三种数据结构用来表示打开文件:
(1)每个进程在进程记录表中都会有一个记录项,记录项中包含一张打开文件描述符表。有每个文件描述符相关联的是:
a)文件描述符标志;
b)指向一个文件表项的指针;
(2)内核为所有打开文件维持一张文件表,每个文件表项包含:
a)文件状态标志;
b)当前文件的偏移量;
c)指向该文件v节点表项的指针;
(3)每个打开文件(或设备)都有一个v节点结构。

APUE 学习笔记 —— 文件I/O
该图显示了一个进程打开多个文件的场景。打开文件描述符表可以存放在用户空间,而非进程表中。
APUE 学习笔记 —— 文件I/O
该图展示了多个独立的进程打开同一个文件的场景。此场景在读的时候,可以正确的读。但是当涉及到写文件,就会存在了一些不可预料的结果。

dup 与 dup2 函数

APUE 学习笔记 —— 文件I/O
两个函数都是用来复制一个现有的文件描述符的。有 dup 返回的新文件描述符一定是当前可用文件描述符中的最小值,对于 dup2,可以用fd2参数指定新描述符的值。如果fd2已经打开,则将其关闭先。若fd=fd2,则dup2返回fd2,而不关闭它。
APUE 学习笔记 —— 文件I/O
![

sync、fsync、fdatasync 函数

APUE 学习笔记 —— 文件I/O
传统的unix系统都会在内核中设有缓冲区告诉缓存或页高速缓存,大多数磁盘io都是通过缓冲区进行。当向文件写数据时,内核通常会先将数据copy到缓冲区中,然后排入队列,晚些时候会写入到磁盘中,这被称为延迟写。当内核需要重用缓冲区来存放其他睡的时候,会将所有数据写入到磁盘中。为了保证磁盘上实际文件系统与缓冲区中内容的一致性,unix系统提供了三种函数,如上。它们有什么区别呢?
APUE 学习笔记 —— 文件I/O

fcntl 函数

APUE 学习笔记 —— 文件I/O
fcntl 函数可以改变已经打开的文件的属性。
APUE 学习笔记 —— 文件I/O
fcntl 的返回值与命令有关。如果出错,所有命令都返回-1;成功会返回其他值。
在修改文件描述符标志或文件状态标志的时候必须谨慎,先要获取现在的标志值,然后再按照期望修改它,最后设置新的标志值。本小节还讲到了调用write时设置同步机制后,对系统性能带来的影响。

ioctl 函数

APUE 学习笔记 —— 文件I/O