萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 網路安全 >  >> 網路基礎知識

Linux 系統編程核心基礎(三):文件描述符與 open/read/write 內核交互圖解

在 Linux 內核中,每個進程由 task_struct 描述,其中指向 files_struct 的指針構成了文件描述符表。用戶程式無法直接訪問內核表項,只能持有文件描述符——即表項索引(非負整數:0、1、2、3…)。本文通過圖解剖析文件描述符從分配到讀寫的完整內核路徑。

核心數據結構關係圖

task_struct (進程描述符/PCB)
  └─ files_struct *files  →  文件描述符表 (fd table)
        ├─ fd[0] → struct file * → stdin  (標準輸入)
        ├─ fd[1] → struct file * → stdout (標準輸出)
        ├─ fd[2] → struct file * → stderr (標準錯誤)
        ├─ fd[3] → struct file * → 打開的文件 A
        └─ fd[n] → struct file * → 打開的文件 N
文件描述符表與 struct file 關係圖
文件描述符表項指向 struct file,進而指向 dentry/inode 與具體文件系統

關鍵流程:open → 讀寫 → close

  1. open(path, flags, mode):
    內核在進程 fd 表中尋找最小未用索引 fd,分配 struct file,初始化 f_pos=0、f_flags、f_op(文件操作函數表),調用文件系統 inode->i_fop->open(),將 fd 返回用戶態。
  2. read(fd, buf, count) / write(fd, buf, count):
    用戶態傳入 fd → 內核通過 files_struct->fd[fd] 找到 struct file * → 調用 f_op->read()/write() → 複製數據至/自用戶緩衝區 → 更新 f_pos → 返回實際字節數。
  3. close(fd):
    內核釋放 struct file(引用計數歸零時觸發 f_op->release()),fd 表項置空,該 fd 可被復用。

三大標準流與繼承特性

  • fd 0/1/2:進程創建時自動關聯終端設備(/dev/pts/x 或 /dev/console),對應 stdin/stdout/stderr。
  • fork() 子進程繼承父進程 fd 表:指向同一 struct file,共享文件偏移量 f_pos、狀態標誌。這是 Shell 管道、重定向、守護進程標準流重定向的基礎。
  • exec() 替換映像保留 fd:除非設定 FD_CLOEXEC(close-on-exec),文件描述符跨 exec 保留。

進階:文件描述符 vs 文件指標 (FILE*)

理解文件描述符機制,是掌握 Linux 高性能 I/O(epoll/IO_uring)、進程間通信、容器隔離、沙箱技術的基石。建議配合 strace -f -e trace=open,read,write,close 程式 觀察實際系統調用流程。

copyright © 萬盛學電腦網 all rights reserved
維度文件描述符文件指標
本質內核 fd 表索引用戶態緩衝 I/O 封裝
頭文件<unistd.h>, <fcntl.h><stdio.h>
APIopen/read/write/close/lseek/ioctlfopen/fread/fwrite/fclose/fseek/printf
緩衝無(直接系統調用)全緩衝/行緩衝/無緩衝
線程安全原子操作需自行加鎖(或用 flockfile)
轉換fileno(FILE*) → fdfdopen(fd, mode) → FILE*