磁碟檔案、終端機、Socket、管道、裝置... 統一以 檔案描述符 (File Descriptor, FD) 代表,操作介面統一:read, write, close, ioctl。
| 特性 | Unbuffered I/O (syscall) | Buffered I/O (stdio.h) |
|---|---|---|
| 函式 | read, write, open, close, lseek | fread, fwrite, fopen, fclose, fseek, fprintf |
| 標頭檔 | unistd.h, fcntl.h | stdio.h |
| 緩衝 | 無 (直接進核心) | 有 (用戶空間緩衝區,預設 4KB/行緩衝/無緩衝) |
| 適用場景 | 精確控制、Socket、裝置、高效能 | 一般文字/二進位檔案處理 |
| 執行緒安全 | 原子性由核心保證 | 需鎖保護 (FILE* 內部鎖) |
ssize_t read(int fd, void *buf, size_t count); // 成功>0 返回讀取位元組數,0=EOF,-1=錯誤
ssize_t write(int fd, const void *buf, size_t count); // 成功>0 返回寫入位元組數,-1=錯誤
// 完整讀取 n 位元組
ssize_t readn(int fd, void *buf, size_t n) {
size_t left = n; char *p = buf;
while (left > 0) {
ssize_t r = read(fd, p, left);
if (r < 0) { if (errno == EINTR) continue; return -1; }
if (r == 0) break; // EOF
left -= r; p += r;
}
return n - left;
}
// 完整寫入 n 位元組
ssize_t writen(int fd, const void *buf, size_t n) {
size_t left = n; const char *p = buf;
while (left > 0) {
ssize_t w = write(fd, p, left);
if (w < 0) { if (errno == EINTR) continue; return -1; }
left -= w; p += w;
}
return n;
}
read 無資料時阻塞執行緒。簡單但併發需多執行緒/多行程,資源消耗大fcntl(fd, F_SETFL, O_NONBLOCK)。read 無資料立即返回 EAGAIN/EWOULDBLOCK。需輪詢,CPU 佔用高select, poll, epoll (Linux)、kqueue (BSD/macOS)、IOCP (Windows)。單執行緒監控成千上萬 FD,就緒時才處理。高併發伺服器標準架構每連線一執行緒:accept → 建立執行緒 → 執行緒循環 read 處理業務。連線數大時執行緒切換開銷成為瓶頸 → 引入 I/O 多路復用 + 執行緒池 (Reactor/Proactor 模式)。
行程控制 (fork, exec, waitpid, 訊號處理)、執行緒同步 (mutex, condvar, rwlock)、鎖自由程式設計。敬請期待。