學過計系肯定了解 寄存器、程序計數器、堆棧這些 程序運行需要的資源。 這些是進程地址空間。
而操作系統分配一個進程資源時,分配的是 PCB 進程控制塊。
所以進程控制塊還維護其他資源——程序與外部交互的資源——文件、管道、套接字。
文章目錄
- 文件描述符
- 進程管理
- exec() 之后文件描述符的情況
文件描述符
文件描述符(File Descriptor, FD)是由操作系統管理的資源,并不會存儲在用戶進程的地址空間,而是由內核維護,并在進程控制塊(PCB)中記錄。
用戶態的進程只能通過 fd(整數)間接訪問文件,無法直接訪問內核中的文件數據。
進程管理
┌───────────────────┐
│ 進程控制塊(PCB) │
│ ┌───────────────┐ │
│ │ 文件描述符表 │ │ <--- 用戶進程訪問的 `fd` 存在這里
│ │ (fd 0 -> stdin) │
│ │ (fd 1 -> stdout) │
│ │ (fd 2 -> stderr) │
│ │ (fd 3 -> socket) │
│ └───────────────┘ │
└───────────────────┘
┌───────────────────────┐
│ 文件描述符表【進程私有】│
│ fd 3 -> 指向打開文件表 │
└───────────────────────┘↓
┌───────────────────┐
│ 打開文件表【系統共享】│
│ 記錄文件偏移量、模式 │
└───────────────────┘↓
┌───────────────────┐
│ VFS【文件系統】 │
│ 指向具體文件數據 │
└───────────────────┘
exec() 之后文件描述符的情況
exec() 不會 清空進程的文件描述符表(除非 FD_CLOEXEC 標志被設置)。
fcntl(pipefd[1], F_SETFD, FD_CLOEXEC); // 讓寫端在 exec() 后自動關閉可以設置這個標志位
其實就是 close after exec ~
文件描述符仍然指向原來的打開文件表和 VFS 層的文件對象,因此 exec() 后仍可使用繼承的 fd(如管道、套接字)。