文件和文件描述符

文件和文件描述符

2024 南京大学《操作系统:设计与实现》
文件和文件描述符

Everything is a File

访问操作系统中的对象

  • 文件:有 “名字” 的对象
  • 字节流 (终端) 或字节序列 (普通文件;包括 /proc/*)

文件描述符

  • 指向操作系统对象的 “指针”
    • 通过指针可以访问 “everything”
  • 对象的访问都需要指针
    • open, close, read/write (解引用), lseek (指针内赋值/运算), dup (指针间赋值)
2024 南京大学《操作系统:设计与实现》
文件和文件描述符

应用程序:访问文件

通过系统调用

  • open, read, write, mmap, ...
  • (当然可以;我们实现过很多这样的程序了)

真的是这样吗?

  • 求证:strace readelf -h /bin/ls
  • 还有更多有趣的例子
    • LC_ALL=zh_CN.UTF-8 strace readelf -h a.txt
    • “不是 ELF 文件 - 它开头的 magic 字节错”?
      • (需要 language-pack-zh-hans)
      • 计算机世界没有魔法!
2024 南京大学《操作系统:设计与实现》
文件和文件描述符

更多的细节 (1)

文件是 “虚拟磁盘”

  • 把磁盘的一部分映射到地址空间,再自然不过了
mmap(addr, length, prot, flags, fd, offset);

一些细节问题

  • 映射的长度超过文件大小会发生什么?
    • ATFAI? GPT-4o 答错了,但给了一个正确的示例代码 😂
      • 启发:langchain (self-validation) 是趋势
    • RTFM 看来还是有用的 (“Errors”): SIGBUS
      • ftruncate 可以改变文件大小
2024 南京大学《操作系统:设计与实现》
文件和文件描述符

更多的细节 (2)

文件访问的 offset

  • 文件的读写自带 “游标”
    • 省去了进程保存文件读/写的位置

Offset 管理

  • read/write: 会自动维护 offset
  • lseek: 修改 offset 位置
    • 对比:mmap file,实现 append 是个噩梦
2024 南京大学《操作系统:设计与实现》
文件和文件描述符

更多的细节 (3)

mmap, lseek, ftruncate 互相交互的情况

  • 假设初始时文件大小为 2MB
    • lseek to 3 MiB (SEEK_SET)
      • 这时候能写入吗?
    • ftruncate to 1 MiB
      • 这时候 offset 在哪里?

水面下的冰山

  • 当多个机制互相作用时,系统就变得复杂
2024 南京大学《操作系统:设计与实现》
文件和文件描述符

更多的细节 (4)

文件描述符在 fork 时会被子进程继承

  • 父子进程共用 offset?
  • 父子进程拥有独立 offset?

请你做一次操作系统的设计者

  • 哪一种方案更合理?
2024 南京大学《操作系统:设计与实现》
文件和文件描述符

偏移量管理:行为

操作系统的每一个 API 都可能和其他 API 有交互 😂

  1. open 时,获得一个独立的 offset
  2. dup 时,两个文件描述符共享 offset
  3. fork 时,父子进程共享 offset
  4. execve 时文件描述符不变
  5. O_APPEND 打开,偏移量永远在最后 (无论是否 fork)
    • modification of the file offset and the write operation are performed as a single atomic step

A fork() in the road

  • (在当时) 好的设计可能成为系统演化过程中的包袱
2024 南京大学《操作系统:设计与实现》