Linux 核心將所有輸入輸出裝置(檔案、管道、Socket、終端機、裝置檔)統一抽象為檔案描述符(File Descriptor, FD)——非負整數。每個進程擁有獨立 FD 表,預設開啟三個標準描述符:
| 名稱 | 巨集 | 數值 | 用途 |
|---|---|---|---|
| 標準輸入 | STDIN_FILENO | 0 | 鍵盤/重導向輸入 |
| 標準輸出 | STDOUT_FILENO | 1 | 螢幕/管道輸出 |
| 標準錯誤 | STDERR_FILENO | 2 | 錯誤訊息輸出 |
| 函式 | 原型 | 說明 | 回傳值 |
|---|---|---|---|
open | int open(const char *path, int flags, mode_t mode); | 開啟/建立檔案,flags 組合:O_RDONLY\|O_WRONLY\|O_RDWR、O_CREAT、O_TRUNC、O_APPEND、O_NONBLOCK 等 | 成功≥0 (FD),失敗 -1 |
read | ssize_t read(int fd, void *buf, size_t count); | 讀取最多 count 位元組至 buf | >0 實際讀取量,0=EOF,-1 錯誤 |
write | ssize_t write(int fd, const void *buf, size_t count); | 將 buf 前 count 位元組寫入 fd | >0 實際寫入量,-1 錯誤 |
close | int close(int fd); | 關閉檔案描述符 | 0 成功,-1 失敗 |
lseek | off_t lseek(int fd, off_t offset, int whence); | 移動檔案偏移量,whence:SEEK_SET/SEEK_CUR/SEEK_END | 新偏移量,-1 錯誤 |
ioctl | int ioctl(int fd, int request, ...); | 裝置控制通用介面(終端機、磁碟、網卡等) | 視 request 而定,-1 錯誤 |
fcntl | int fcntl(int fd, int cmd, ...); | 檔案描述符屬性控制(F_GETFL/F_SETFL、鎖定 F_SETLK、F_SETOWN 等) | 視 cmd 而定,-1 錯誤 |
dup | int dup(int oldfd); | 複製 FD,回傳最小未用 FD | 新 FD,-1 失敗 |
dup2 | int dup2(int oldfd, int newfd); | 指定新 FD 編號,若佔用先關閉 | newfd,-1 失敗 |
mkstemp | int mkstemp(char *template); | 建立唯一暫存檔,template 結尾需 6 個 X,原子操作 | FD,-1 失敗 |
read/write 可能傳輸少於請求位元組(訊號中斷、非阻塞、管道滿/空),必須用迴圈處理殘餘。
ssize_t writen(int fd, const void *buf, size_t n) {
size_t left = n;
const char *p = buf;
while (left > 0) {
ssize_t written = write(fd, p, left);
if (written <= 0) {
if (errno == EINTR) continue; // 被信號中斷,重試
return -1;
}
left -= written;
p += written;
}
return n;
}
O_APPEND 原子附加:多進程同時寫入同一檔案不會覆蓋彼此資料。lseek 不會引發 I/O,僅修改核心檔案表項的偏移量指標。dup2 是 Shell 實現重導向(cmd > file)的核心:dup2(fd, STDOUT_FILENO)。mkstemp 回傳已開啟 FD,避免 tmpnam/mktemp 的競爭條件 (TOCTOU)。int fd = open("data.bin", O_RDONLY);
if (fd < 0) {
perror("open data.bin"); // 輸出 "open data.bin: No such file or directory"
exit(EXIT_FAILURE);
}
所有系統呼叫失敗均設定全域 errno,配合 strerror(errno) 或 perror 診斷。
fcntl 記錄鎖 (F_SETLK/F_SETLKW) 與 flockpoll/epoll 多工mmap:零拷貝、檔案即記憶體readv/writev無緩衝 I/O 雖較標準 C 庫(fopen/fread)繁瑣,但提供精確控制、零拷貝潛力、非阻塞多工能力,是高效能伺服器、資料庫引擎、嵌入式系統的必修內功。