文件I/O

Last edited
Last updated July 14, 2023
Pages
Tags

1. 文件IO介绍

  • 文件 IO 即非缓冲 IO(unbuffered I/O)
  • 它的 readwrite 都是调用内核中的系统调用
  • 它比标准IO更加底层,因此使用文件IO库函数的代码比标准IO的移植性更差,且没有经过优化(例如缓冲区),多数情况下的性能表现更差
  • 大多数文件IO的实现只须这五个函数: open , read , wirte , lseek , close

2. 文件描述符

  • 对内核而言,所有打开的文件都是文件描述符的引用
  • 文件描述符是一个非负整数
  • 通常由 open 或者 create 创建,传递给 read 或者 write 使用
  • 按照惯例,文件描述符 0 被默认关联给标准输入, 1 被关联给标准输出,文件描述符 2 被关联给标准错误
    • 应当使用 <unistd.h> 中定义的 STDIN_FILENOSTDOUT_FILENOSTDERR_FILENO ,而不是直接使用数字
  • 变化范围为 0~OPEN_MAX-1 ,早期的上限是 19 个,现在一般是 63 个

3. 函数 open 和 openat

  • 用来打开一个文件
#include <fcntl.h> int open(const char *path, int oflag, ... /*mode_t mode*/); int openat(int fd, const char *path, int oflag, ... /*mode_t mode*/);
成功返回文件描述符,错误,返回-1
  • oflag 参数可用一个常量或者多个常量用 | 连接:
    • O_RDONLY 只读打开
    • O_WRONLY 只写打开
    • O_RDWR 读写打开
    • O_APPEND 追加方式打开
    • O_CREAT 若不存在创建
    • O_TRUNC 若存在则长度截断为 0 ,即清空打开
    • ……
  • 返回的文件描述符默认是最小的可用的数字(有其他方法获得指定数字)
  • path 参数如果是绝对路径,此时 openatfd 参数被省略,效果等同 open 函数
  • path 参数如果是相对路径,fd 参数指出了相对路径在文件系统中的开始地址

4. 函数 creat

  • 用来创建一个文件
#include <fcntl.h> int creat(const char *path, mode_t mode);
  • 相当于 open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)

5. 函数 close

  • 用来关闭一个文件
#include <unistd.h> int close(int fd);
  • 释放文件上的记录锁
  • 进程中止的时候,内核会自动关闭它的所有文件

6. 函数 lseek

  • 每个文件都有一个当前文件偏移量(current file offset)
  • 相当于一个光标在文档中的座标
  • 通过 lseek 函数可以设置偏移量:
#include <unistd.h> off_t lseek(int fd, off_t offset, int whence);
  • whence 是一个常量,
    • SEEK_SET 将偏移量设置为距离文件开始处 offset 个字节
    • SEEK_CUR 将偏移量设置为当前值加上 offset ,可为负数
    • SEEK_END 将偏移量设置为文件长度加上 offset ,可正可负
  • 函数执行成功后,返回新的偏移量
  • 偏移量的设置记录在内核中,不进行任何 I/O 操作
  • 空洞文件:将一个空文件的偏移量设置到指定大小,写入一个字符后保存,该文件将会在磁盘上占用掉指定的大小(比如迅雷下载文件),代码参考 APUE 第三版图 3-2

7. 函数 read

  • 从文件中读数据
#include <unistd.h> ssize_t read(int fd, void *buf, size_t nbytes);
  • 成功后返回读到的字节数

    8. 函数 write

     

    参考资料

    • (第三版)》第 3 章 - 文件 I/O