首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux 文件描述符複製機制:dup 與 dup2 深度剖析

     編輯:關於C語言

核心概念:文件描述符與 file 結構體

文件描述符 (fd) 是進程持有的整數句柄,指向內核 file 結構體。file 結構體包含:

  • 文件狀態標志 (O_APPEND, O_NONBLOCK 等)
  • 當前讀寫偏移量
  • 引用計數 (f_count)
  • 指向 inode 的指針

關鍵區別:dup vs 兩次 open

操作fd 關係file 結構體共享屬性
dup/dup2指向同一 file同一個偏移量、狀態標志共享,引用計數+1
兩次 open指向不同 file兩個獨立偏移量、標志獨立,引用計數各 1

API 簽名與行為


#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
  • 成功返回新 fd,失敗返回 -1
  • dup:返回進程最小未用 fd(同 open)
  • dup2:指定 newfd;若 newfd 已打開則先關閉;若 oldfd == newfd 直接返回

經典案例:輸出重定向


int main() {
    int fd = open("somefile", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
    int save_fd = dup(STDOUT_FILENO);  // 保存標準輸出
    dup2(fd, STDOUT_FILENO);           // 標準輸出 → somefile
    close(fd);
    write(STDOUT_FILENO, "This is a test\n", 15);  // 寫入文件
    dup2(save_fd, STDOUT_FILENO);      // 恢復標準輸出
    write(STDOUT_FILENO, "This is a test\n", 15);  // 寫入終端
    close(save_fd);
    return 0;
}

流程圖解:引用計數變化

dup/dup2 引用計數變化示意

關鍵時刻分析

  1. dup(STDOUT_FILENO):save_fd 與 1 指向同一 tty file,引用計數 2
  2. dup2(fd, 1):關閉 fd 1 (tty 引用計數 2→1),fd 1 指向 somefile file (引用計數 1→2)
  3. close(fd):somefile 引用計數 2→1 (fd 1 仍持有)
  4. dup2(save_fd, 1):關閉 fd 1 (somefile 引用計數 1→0,真正關閉),fd 1 指向 tty (引用計數 1→2)
  5. close(save_fd):tty 引用計數 2→1

實戰應用場景

  • Shell 重定向:cmd > file 實質是 dup2(open("file"), 1)
  • 管道實現:pipe(fd); dup2(fd[1], STDOUT_FILENO); dup2(fd[0], STDIN_FILENO)
  • 守護進程:重定向標準輸入輸出錯誤到 /dev/null
  • 文件鎖協調:複製 fd 實現鎖傳遞

常見誤區

  1. 以為 dup2 關閉 newfd 會關閉底層文件 —— 僅減引用計數,歸零才真關閉
  2. 混淆 dup 與 fcntl(fd, F_DUPFD) —— 後者可指定最小 fd
  3. 忽略 close-on-exec 標志 —— dup2 不複製此標志,fcntl(fd, F_DUPFD_CLOEXEC) 可設置

總結

dup/dup2 是 Unix「一切皆文件」哲學下文件描述符操作的基石。理解 file 結構體共享語義與引用計數機制,是掌握重定向、管道、進程間文件傳遞的鑰匙。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved