在 Linux 世界裡,「一切皆檔案」。無論是普通檔案、目錄、裝置、Socket,還是管道,核心都統一用檔案描述符 來管理。掌握低層 I/O (Low-level I/O) 是進行系統程式開發、理解高階庫 (如 `stdio.h`) 底層運作的基石。本文詳細講解檔案描述符概念、核心系統呼叫 `open`、`close`、`creat` 及其關鍵細節。
| 特性 | 高階 I/O (Standard I/O) | 低階 I/O (System I/O) |
|---|---|---|
| 代表函數庫 | `stdio.h` (`fopen`, `fread`, `fprintf`...) | `unistd.h`, `fcntl.h` (`open`, `read`, `write`...) |
| 緩衝機制 | 帶緩衝 (全緩衝/行緩衝/無緩衝) | 無緩衝 (直接呼叫核心) |
| 資料類型 | `FILE *` (檔案指標) | `int` (檔案描述符 fd) |
| 適用場景 | 一般應用開發、格式化輸出 | 系統程式、高效能需求、精確控制 |
#include
#include
#include
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode); // 若 flags 含 O_CREAT
關鍵 flags (可按位或 `|` 組合):
O_WRONLY、O_RDWR返回值:成功返回新 fd (最小未用非負整數);失敗返回 -1,設定 `errno`。
#include
int close(int fd);
#include
int creat(const char *pathname, mode_t mode);
等價於:`open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode)`
#include
#include
#include
#include
#include
int main() {
const char *path = "demo.txt";
// 原子性建立:不存在才建立,避免競態條件
int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644);
if (fd == -1) {
if (errno == EEXIST) {
fprintf(stderr, "檔案已存在,拒絕覆蓋\n");
} else {
perror("open 失敗");
}
return 1;
}
const char *msg = "Hello, Low-level I/O!\n";
ssize_t written = write(fd, msg, strlen(msg));
if (written == -1) {
perror("write 失敗");
}
if (close(fd) == -1) {
perror("close 失敗"); // 關鍵:檢查 close 返回值
}
return 0;
}
掌握低階 I/O,不僅能寫出高效、健壯的系統程式,更能深入理解 C 標準庫、C++ iostream 乃至各類高階框架的底層運作原理。