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

APUE 文件 I/O 進階(二):系統級 I/O、文件描述符、原子操作與 I/O 多路複用基礎

     編輯:關於C語言

系統 I/O vs 標準 I/O

維度標準 I/O (stdio)系統 I/O (syscall)
可移植性高 (ANSI C)較低 (POSIX)
性能用戶態緩衝,較慢直達內核,較快
功能豐富度基礎完整 (非阻塞、異步、鎖、屬性...)

1. 文件描述符

非負整數,內核為每個進程維護的打開文件表索引。0=stdin, 1=stdout, 2=stderr。上限 ulimit -n (預設 1024)。

文件描述符結構圖

  • 進程表 → 文件描述符表 → 打開文件表項 → v-node (inode) → 磁碟
  • 多進程可共享同一打開文件表項(fork 繼承、Unix 域套接字傳遞)

2. 核心系統調用

open(const char *path, int flags, mode_t mode)

flags 必選 (三選一): O_RDONLY, O_WRONLY, O_RDWR
flags 可選 (位或): 
  O_CREAT      // 不存在則創建,需提供 mode
  O_APPEND     // 追加寫入
  O_TRUNC      // 截斷為 0
  O_EXCL       // 配合 O_CREAT,文件存在則報錯
  O_NONBLOCK   // 非阻塞模式
  O_SYNC       // 同步寫入 (數據+元數據)
  O_DIRECT     // 繞過頁面緩衝
  O_CLOEXEC    // exec 時自動關閉 (安全)
mode: 八進制權限 (如 0644),實際權限 = mode & ~umask

close(int fd)

釋放描述符,引用計數歸零時才真正關閉底層對象。

read(int fd, void *buf, size_t count) / write(int fd, const void *buf, size_t count)

  • 返回值:實際傳輸位元組數 (非對象數);0 表示 EOF (read) 或無寫入;-1 表示錯誤
  • 短計數:可能少於請求數量 (信號中斷、非阻塞、管道滿等),必須循環調用

lseek(int fd, off_t offset, int whence)

移動文件偏移量。whence: SEEK_SET, SEEK_CUR, SEEK_END。返回新偏移量。支援 64 位 (off_t),可建立稀疏文件。

3. 原子操作

多步驟合為單一不可中斷操作,避免競態條件。

臨時文件創建

  • tmpnam():不原子,僅生成唯一名稱,創建時可能被搶佔
  • tmpfile():原子,內核直接創建並打開,返回 FILE*,關閉時自動刪除

文件鎖與 fcntl

struct flock { short l_type; short l_whence; off_t l_start; off_t l_len; pid_t l_pid; };
fcntl(fd, F_SETLK, &lock);   // 非阻塞加鎖
fcntl(fd, F_SETLKW, &lock);  // 阻塞加鎖
fcntl(fd, F_GETLK, &lock);   // 測試鎖

記錄鎖 (Record Locking):支援字節範圍共享/排他鎖,建議性 (advisory),需協作進程遵守。

4. 描述符複製與重定向

  • dup(int oldfd):返回最小可用新描述符
  • dup2(int oldfd, int newfd):原子指定新描述符,若 newfd 已打開則先關閉

實現輸出重定向:

int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
dup2(fd, STDOUT_FILENO);  // 將 stdout (1) 重定向到 fd
close(fd);
printf("這行會寫入 log.txt\n");

5. ioctl 與 /dev/fd

  • ioctl(fd, request, ...):設備專用控制命令 (如終端屬性、磁碟幾何、網卡配置)
  • /dev/fd/N:打開等同於 dup(N),Shell 重定向常用 (cmd /dev/fd/3 3<input)

6. 效能分析:time 命令

$ time ./mycp large.iso copy.iso
real  1m30.014s  // 用戶等待總時間
user  0m0.003s   // 用戶態 CPU 時間
sys   1m29.003s  // 內核態 CPU 時間 (系統調用開銷)

緩衝區大小權衡:過小 → 系統調用頻繁;過大 → 記憶體壓力、缺頁中斷。典型 4KB-64KB。

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