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

C程序設計語言精華筆記(五):UNIX 系統接口、I/O 系統調用與標準庫實現原理

     編輯:關於C語言

文件描述符

UNIX「一切皆文件」。Shell 啟動程序時預打開 3 個描述符:

  • 0 - stdin(標準輸入)
  • 1 - stdout(標準輸出)
  • 2 - stderr(標準錯誤)

重定向 prog < in > out 由 Shell 修改描述符 0/1 指向,程序無感知。

底層 I/O:read / write

ssize_t read(int fd, void *buf, size_t n);
ssize_t write(int fd, const void *buf, size_t n);
  • 返回實際傳輸字節數;read 返回 0 表示 EOF,-1 表示錯誤。
  • 無緩衝,每次調用陷入內核。塊大小通常取 1(無緩衝字符)或 4KB(匹配磁盤塊)。

無緩衝 getchar 實現

int getchar(void) {
    char c;
    return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;
}

帶緩衝 getchar 實現(標準庫風格)

int getchar(void) {
    static char buf[BUFSIZ];
    static char *bufp = buf;
    static int n = 0;
    if (n == 0) {
        n = read(0, buf, sizeof buf);
        bufp = buf;
    }
    return (n-- > 0) ? (unsigned char)*bufp++ : EOF;
}

文件控制:open / creat / close / unlink

函數原型說明
openint open(const char *path, int flags, mode_t mode)flags: O_RDONLY/O_WRONLY/O_RDWR/O_CREAT/O_TRUNC/O_APPEND
creatint creat(const char *path, mode_t mode)等價 open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)
closeint close(int fd)釋放描述符,不刷新緩衝(無緩衝)
unlinkint unlink(const char *path)刪除目錄項,引用計數歸零時真正刪除文件

權限 mode:八進制如 0666(rw-rw-rw-),受 umask 影響。

隨機訪問:lseek

off_t lseek(int fd, off_t offset, int whence);
// whence: SEEK_SET(0) 開頭, SEEK_CUR(1) 當前, SEEK_END(2) 結尾
// 返回新偏移量,-1 表示錯誤

應用:lseek(fd, 0, SEEK_END) 定位尾部實現追加寫入。

標準庫 fopen / getc 實現原理

FILE 結構體(簡化版):

typedef struct _iobuf {
    int cnt;       // 剩餘字符數
    char *ptr;     // 下一字符指針
    char *base;    // 緩衝區基址
    int flag;      // 標誌位
    int fd;        // 文件描述符
} FILE;

標誌位(位掩碼):_READ(01) _WRITE(02) _UNBUF(04) _EOF(010) _ERR(020)。

全局表:FILE _iob[OPEN_MAX],預置 stdin/stdout/stderr。

getc 宏:

#define getc(p) (--(p)->cnt >= 0 ? (unsigned char)*(p)->ptr++ : _fillbuf(p))

_fillbuf 填充緩衝區:

int _fillbuf(FILE *fp) {
    int bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ;
    if ((fp->flag & (_READ | _EOF | _ERR)) != _READ) return EOF;
    if (fp->base == NULL) fp->base = malloc(bufsize);
    fp->ptr = fp->base;
    fp->cnt = read(fp->fd, fp->ptr, bufsize);
    if (--fp->cnt < 0) { /* 設置 EOF/ERR */ return EOF; }
    return (unsigned char)*fp->ptr++;
}

fopen 核心邏輯:解析模式 → 在 _iob 找空槽 → open/creat 獲取 fd → 填充 FILE 結構 → 返回指針。

性能與可移植性忠告

  • 優先用小範圍整型(short)節省內存/提速。
  • 聲明時初始化(int x = 0;)比賦值快。
  • c += 5 僅求值一次,c = c + 5 求值兩次。
  • && 將最可能為假的條件左置;|| 將最可能為真的左置(短路求值)。
  • 用 EOF 而非 -1(ANSI 只保證負數)。
  • 跨平台處理大整數用 long(至少 32 位)。

函數原型

int maximum(int, int, int);  // 參數名可省略

作用:編譯期檢查參數個數/類型/順序,自動進行參數類型轉換(如傳 int 給 double 參數)。

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