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

Linux C語言檔案操作函式完整指南(二):檔案描述符、select、管道與進程間通訊

     編輯:關於C

格式化 I/O 函式族

int printf(const char *fmt, ...);           // = fprintf(stdout, fmt, ...)
int scanf(const char *fmt, ...);              // = fscanf(stdin, fmt, ...)
int fprintf(FILE *stream, const char *fmt, ...);
int fscanf(FILE *stream, const char *fmt, ...);
int sprintf(char *str, const char *fmt, ...); // 寫入字串緩衝區
int sscanf(const char *str, const char *fmt, ...); // 從字串讀取

f* 系列操作檔案串流,s* 系列操作記憶體字串。

檔案描述符層級操作(POSIX,非 ANSI C)

核心為每進程維護開啟檔案表,描述符為小正整數(0-1023,0/1/2 已佔用)。常用函式:open/creat/close/read/write/ftruncate/lseek/fsync/fstat/fchmod/flock/fcntl/dup/dup2/select/ioctl。

開啟檔案

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>
int open(const char *path, int flags);                    // flags: O_RDONLY/O_WRONLY/O_CREAT 等
int open(const char *path, int flags, mode_t mode);       // 帶權限模式
// 失敗回傳 -1,flags/mode 為位元遮罩組合

讀寫與定位

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);   // 讀至 buf,成功回傳位元組數,EOF 0,錯誤 -1
ssize_t write(int fd, const void *buf, size_t count); // 從 buf 寫入
// fd=1 寫標準輸出,fd=0 讀標準輸入

檔案狀態資訊

#include <sys/stat.h>
int stat(const char *path, struct stat *buf);   // 透過路徑取得
int fstat(int fd, struct stat *buf);            // 透過描述符取得
// 成功 0,失敗 -1(errno 存錯誤碼),man stat 查結構體欄位

多工 I/O:select 機制

#include <sys/select.h> #include <sys/time.h>
int select(int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout);
// 回傳:就緒描述符數、0(超時)、-1(錯誤)
// maxfd: 最大描述符+1;timeout: NULL=永久等待,0=非阻塞輪詢

fd_set 操作巨集:FD_ZERO 清空、FD_SET 加入、FD_CLR 移除、FD_ISSET 測試。使用流程:初始化集合 → select 等待 → 輪詢 FD_ISSET 處理就緒描述符 → FD_CLR 清理。

struct timeval { long tv_sec; long tv_usec; };

檔案描述符轉檔案指標:fdopen

FILE *fdopen(int fildes, const char *mode);

將現有描述符(來自 open/pipe/socket 等)關聯標準 I/O 串流。mode 必須與原描述符讀寫模式一致。常用於管道、網路通訊通道無法用 fopen 開啟的情況。

進程間通訊:管道

命名管道 (FIFO) + popen/pclose

FILE *popen(const char *command, const char *mode); // mode: "r" 讀命令輸出, "w" 寫命令輸入
int pclose(FILE *fp);

範例 1:讀取命令輸出

FILE *fp = popen("cat /etc/profile", "r");
char buf[512];
while (fgets(buf, sizeof(buf), fp)) puts(buf);
pclose(fp);

範例 2:寫入命令輸入

char buf[] = "aaa bbb ccc";
FILE *fp = popen("wc -w", "w");
fwrite(buf, sizeof(buf), 1, fp);
pclose(fp);

無名管道 pipe()

int pipe(int fds[2]); // fds[0] 讀端, fds[1] 寫端,成功 0,失敗 -1
// 必須有父子關係繼承描述符,進程結束管道自動消失

父寫子讀範例

int fds[2]; pipe(fds);
if (fork() == 0) {          // 子進程
    close(fds[1]); sleep(2);
    read(fds[0], buf, sizeof(buf)); puts(buf);
    close(fds[0]); exit(0);
} else {                    // 父進程
    close(fds[0]);
    write(fds[1], "hello", 6);
    waitpid(-1, NULL, 0);
    close(fds[1]); exit(0);
}

雙向管道聊天室(FIFO + fork + select)

伺服器端:永久 FIFO 僅讀 → select 監聽上線/訊息/下線 → 廣播訊息給所有在線客戶端。
客戶端:向伺服器 FIFO 寫入 PID → 建立雙向 FIFO → fork 父進程寫/子進程讀。

完整代碼請參考原文(含 sever.c 與 myclient.c 實現)。

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