Unix I/O

文件是一个字节序列。 所有的 IO 设备都视为文件,所有 IO 都以一种统一的方式进行处理。

文件

  • 普通文件,包含任意数据
  • 目录文件,包含一组链接,每个链接将一个文件名映射到一个文件
  • 套接字,用来与另一个进程进行跨网络通信的文件

打开和关闭文件

打开文件

open 函数,若成功返回新文件的描述符,若出错返回 -1

关闭文件

close 函数,若成功则为 0,若出错则为 -1

  • 关闭已关闭的文件会返回错误
  • 一个进程终止时内核对该进程所有未关闭的文件描述符调用 close
  • 成功关闭并不确保数据已经保存到磁盘

读写文件

读文件

read 函数,若成功返回读的字节数,若 EOF 返回 0,若出错返回 -1

写文件

write 函数,若成功返回写的字节数,若出错则返回 -1

  • 读写过程中返回值比要求的读写字节值少是可能的,不是错误,可能在以下情况发生
    • 读到 EOF
    • 从终端读入文本行
    • 从 socket 读写数据
  • 读写不足不会在以下情况发生
    • 从磁盘读取(除 EOF)
    • 向磁盘写入

读取文件元数据

元数据是关于文件的信息。 stat 函数以文件名为输入,填写一个 stat 结构体。 若成功返回 0,出错返回 -1

读取目录内容

opendir 函数返回指向目录流的指针,若出错则为 NULL readdir 函数返回指向流中的下一个目录项的指针,若没有更多目录项,返回 NULL

  • 每个目录项包含索引节点号和文件名 closedir 函数关闭流并释放资源

共享文件

  • 描述符表:每个进程独立,每个打开的描述符表项指向文件表中的一个表项
  • 文件表:所有进程共享。每个文件表表项包括当前文件位置、引用计数和一个指向 v-node 表中表项的指针
  • v-node表:所有进程共享。每个表项包含 stat 结构中的大多数信息 多个描述符可以通过不同的文件表表项来引用同一个文件。例如,用相同的文件名 open 两次。 子进程继承父进程的描述符表,打开文件表中的引用计数加一。

I/O 重定向

int dup2(int oldfd, int newfd);

dup2 函数,复制 oldfdnewfd 如果 newfd 已经打开了,则会在复制 oldfd 前关闭 newfd

标准 I/O

标准 I/O 库将一个打开的文件模型化为一个流,即一个指向 FILE 类型的指针,每个 C 程序开始时都有三个打开的流 stdinstdoutstderr

Unix I/O vs 标准I/O

标准 I/O 和 RIO 都是用 Unix I/O 实现的。

  • Unix I/O 开销最小,提供了访问文件元数据的功能,但是对不足值处理不够,容易出错
  • 标准 I/O 通过使用缓冲增加了效率,且可以自动处理不足值,但是没有提供访问文件元数据的功能,且不是同步信号安全的