文件和文件描述符
文件和文件描述符
文件和文件描述符
Everything is a File
访问操作系统中的对象
文件:有 “名字” 的对象
字节流 (终端) 或字节序列 (普通文件;包括 /proc/*)
文件描述符
指向操作系统对象的 “指针”
通过指针可以访问 “everything”
对象的访问都需要指针
open, close, read/write (解引用), lseek (指针内赋值/运算), dup (指针间赋值)
文件和文件描述符
应用程序:访问文件
通过系统调用
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)
计算机世界没有魔法!
文件和文件描述符
更多的细节 (1)
文件是 “虚拟磁盘”
把磁盘的一部分映射到地址空间,再自然不过了
mmap(addr, length, prot, flags, fd, offset);
一些细节问题
映射的长度超过文件大小会发生什么?
ATFAI? GPT-4o 答错了,但给了一个正确的示例代码
启发:langchain (self-validation) 是趋势
RTFM 看来还是有用的 (“Errors”): SIGBUS
ftruncate 可以改变文件大小
文件和文件描述符
更多的细节 (2)
文件访问的 offset
文件的读写自带 “游标”
省去了进程保存文件读/写的位置
Offset 管理
read/write: 会自动维护 offset
lseek: 修改 offset 位置
对比:mmap file,实现 append 是个噩梦
文件和文件描述符
更多的细节 (3)
mmap, lseek, ftruncate 互相交互的情况
假设初始时文件大小为 2MB
lseek to 3 MiB (SEEK_SET)
这时候能写入吗?
ftruncate to 1 MiB
这时候 offset 在哪里?
水面下的冰山
当多个机制互相作用时,系统就变得复杂
文件和文件描述符
更多的细节 (4)
文件描述符在 fork 时会被子进程继承
父子进程共用 offset?
父子进程拥有独立 offset?
请你做一次操作系统的设计者
哪一种方案更合理?
文件和文件描述符
偏移量管理:行为
操作系统的每一个 API 都可能和其他 API 有交互
open 时,获得一个独立的 offset
dup 时,两个文件描述符共享 offset
fork 时,父子进程共享 offset
execve 时文件描述符不变
O_APPEND 打开,偏移量永远在最后 (无论是否 fork)
modification of the file offset and the write operation are performed as a single atomic step
A
fork()
in the road
(在当时) 好的设计可能成为系统演化过程中的包袱