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

文件描述符

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

open 与 openat 函数的使用

  • oflag 参数:
    是通过在头文件 <fcntl.h> 中定义的常量中的一个或多个进行 “或”运算构成的。这里不再一一详述每个常量及其含义,感兴趣的小伙伴可以自行去查阅。
  • path 参数:
    是要打开和创建文件的名字。
  • fd 参数:
    fd 把open 和 openat 函数区分开来,具体有三种可能:

    1. 当path是绝对路径时, openat 就相当于是 open;
    2. path制定的是相对路径名称时,fd指出了相对路径名称的在文件系统中的开始位置;
    3. path是相对路径,fd参数具有特殊值 AT_FDCWD。此时,路径名在当前工作目录中获取,openat 函数在操作上与 open 函数类似;
      本节还讲到了 TOCTTOU 思想以及文件名与路径名被截断的问题。

creat 函数


creat函数是以只写的形式来打开一个新的文件的。

close 函数


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

lseek 函数


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

read 函数


如果 read 成功,则会返回读到的字节数。如果已经读到了文件的末尾,会返回0。

write 函数


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

I/O 效率

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

文件共享

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


该图显示了一个进程打开多个文件的场景。打开文件描述符表可以存放在用户空间,而非进程表中。

该图展示了多个独立的进程打开同一个文件的场景。此场景在读的时候,可以正确的读。但是当涉及到写文件,就会存在了一些不可预料的结果。

dup 与 dup2 函数


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

![dup(1) 后的内核数据结构说明

sync、fsync、fdatasync 函数


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

fcntl 函数


fcntl 函数可以改变已经打开的文件的属性。

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

ioctl 函数

APUE 学习笔记 —— 文件I/O的更多相关文章

  1. APUE学习笔记-文件I/O

    这次回顾APUE中第三四章的内容,主要是文件I/O操作相关的接口函数.    UNIX系统的文件I/O是不带缓冲的I/O,不带缓冲是指每个read和write都调用系统内核的一个系统调用. 1.文件描 ...

  2. APUE学习笔记3_文件IO

    APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...

  3. APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

    转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...

  4. 《python基础教程(第二版)》学习笔记 文件和素材(第11章)

    <python基础教程(第二版)>学习笔记 文件和素材(第11章) 打开文件:open(filename[,mode[,buffering]]) mode是读写文件的模式f=open(r' ...

  5. [Python学习笔记]文件的读取写入

    文件与文件路径 路径合成 os.path.join() 在Windows上,路径中以倒斜杠作为文件夹之间的分隔符,Linux或OS X中则是正斜杠.如果想要程序正确运行于所有操作系统上,就必须要处理这 ...

  6. APUE学习笔记(2):lseek()练习与文件洞

    对于lseek函数早在大一的C语言课上就有接触,但是几乎没有使用过,只记得是和文件偏移操作相关的 看了APUE上的示例,又使用od工具查看了内容,果然很神奇,很新鲜 figure3.2.c [c] # ...

  7. apue学习笔记(第三章 文件I/O)

    本章开始讨论UNIX系统,先说明可用的文件I/O函数---打开文件.读写文件等 UNIX系统中的大多数文件I/O只需用到5个函数:open.read.write.lseek以及close open函数 ...

  8. apue学习笔记(第四章 文件和目录)

    本章将描述文件系统的其他特性和文件的性质. 函数stat.fstat.fstatat和lstat #include <sys/stat.h> int stat(const char *re ...

  9. APUE学习笔记3——文件和目录

    1 简介 之前学习了执行I/O操作的基本函数,主要是围绕普通文件I/O的打开.读或写.下面继续学习Unix文件系统的其他特征和文件的基本性质.我们将从stat函数开始,了解stat结构所代表的文件属性 ...

随机推荐

  1. Resolving Problems installing the Java JCE Unlimited Strength Jurisdiction Policy Files package--转

    原文地址:https://www.ca.com/us/services-support/ca-support/ca-support-online/knowledge-base-articles.tec ...

  2. Xshell调整终端显示的最大行数(缓冲区)

    1 选择会话,按顺序点击文件->属性 ,打开"会话属性"窗口 如下 在"会话属性"窗口中选择“终端” 修改缓冲区大小的值:其范围为0~2147483647 ...

  3. ICA(独立成分分析)笔记

    ICA又称盲源分离(Blind source separation, BSS) 它假设观察到的随机信号x服从模型,其中s为未知源信号,其分量相互独立,A为一未知混合矩阵. ICA的目的是通过且仅通过观 ...

  4. 路飞学城Python-Day15(模块二思维导图)

  5. 2015 Multi-University Training Contest 2 Friends

    Friends Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  6. oracle仿全文检索切词机制实现文本信息类似度查找

    应用场景: 依据keyword查询与此keyword相似的信息,当中一些keyword要排除掉比如:"有限公司"."有限责任公司"."股份有限公司&q ...

  7. 【LeetCode OJ 34】Search for a Range

    题目链接:https://leetcode.com/problems/search-for-a-range/ 题目:Given a sorted array of integers, find the ...

  8. leetCode(38):Lowest Common Ancestor of a Binary Search Tree

    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...

  9. Android5.0以上系统的移动网络开关

    笔者近期遇到一个非常有意思的bug,贴出来和大家分享下. 那是一个温暖的早晨,阳光晒得人非常舒服.一封bug邮件像一片叶子飘到我的邮箱. 一番交流.笔者确认负责的Widget开关在Android5.0 ...

  10. XMPP添加删除好友

    在现阶段的通信服务中.各种标准都有,因此会出现无法实现相互连通,而XMPP(Extensible Message and presence Protocol)协议的出现,实现了整个及时通信服务协议的互 ...