VinSong's Blog

Back

NTU-SP 系統程式設計 Ch4 Buffered I/OBlur image

Buffered I/O#

Standard Library of C#

  • Call fopen() 會得到一個 file object pointer 會放在 Virtual Memory

FILE *fopen(const char *pathname, const char *type);

  • 可以 support atomic operation
  • 截圖 2025-10-17 凌晨12.50.30

FILE *freopen(const char *pathname, const char *type, FILE *fp);

  • 可以指定某個 fp (通常是常見 e.g. STDOUT) 來放這個 file
  • FILE *fp;
    fp = freopen ("/tmp/logfile", "a+", stdout);
    printf(“Sent to stdout and redirected to /tmp/logfile”);
    fclose(stdout);
    c

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

  • 做 unbuffer I/O 後想重新指定型別,所以可以把開好的 fd 來指定型別
    • 一定要是前一個 open 的 subset
  • 如果此時開成 w 會沒有 truncate

int fileno(FILE *fp);

  • 得到 fd

int fclose(FILE *fp);

  • fstream 裡面的 buffer 必須有效
  • 可以把裡面的東西
    • Discard Input
    • Flush Output
  • FILE *open_data(void)
    {
         FILE *fp;
        char databuf[BUFSIZ];  /* setvbuf makes this the stdio buffer */
    
        if ((fp = fopen(DATAFILE, "r")) == NULL)
            return (NULL);
        if (setvbuf(fp, databuf, _IOLBF, BUFSIZ) != 0)
            return (NULL);
    
        return (fp);
    }
    c
  • 這裡的 databuf 是 local 的出去之後 fclose 會失效

Buffering#

  • 最主要目的是要減少 system call 的次數
  • Call standard I/O 會自動 allocate 但是也可以自行 setbuf(), setvbuf()
  • 最終會往 Unbuffer I/O 送

Fully Buffered#

  • Default 通常是這個 e.g. Disk, Pipe, Socket
  • 滿了才會送出去,才 trigger Unbuffer I/O

Line Buffered#

  • New line 就會送一次 e.g. terminal
  • 兩種情況要特殊處理
    • Full: 滿了就一定得送出去
    • Flush: 系統要求一定要馬上 flush
      • 下面這個 code,新一行雖然沒看到 \n 但 terminal 必須先輸出 $
      • char buf[100];
        printf(“$ “); 
        scanf(“%s”, buf); 
        c

Unbuffered#

  • 需要有錯誤就馬上輸出
    • stderr

int fflush(FILE *fp);

  • fp 裡面的 buffer 內容透過 Unbuffer I/O 送出去
  • 如果設定 fp == NULL 就會把所有 output buffer 送出去
  • 送是送到 buffer cache 而不是直接進去 DISK 還要呼叫 sysc(), fsysc(), fdatasysc()

void setbuf(FILE *fp, char *buf);

  • 沒指定 size 會是 system 指定 type

int setvbuf(FILE *fp, char *buf, int mode, size_t size);

  • 可以指定 size,也就是 type 可以指定
  • 透過 stat 去得到 file metadata
    • _IOFBF, _IOLBF, _IONBF

long ftell(FILE *fp);

  • 找尋目前 offset

int fseek(FILE *fp, long offset, int whence);

  • Binary file SEEK_END 無用因為 buffer 性質會 append 一堆奇怪東西
  • Text file SEEK_SET 就是 0 或著 ftell() 的 return value

Unformatted I/O#

  • Character-at-a-time I/O, e.g., getc()
    • Buffering handled by standard I/O lib
  • Line-at-a-time I/O, e.g., fgets()
    • Buffer limit might need to be specified.
  • Direct I/O, e.g., fread()
    • Read/write a number of objects of a specified size

Character-at-a-time I/O#

int getc(FILE *fp); int fgetc(FILE *fp); int getchar(void);

  • getc() 有可能是 macro, getchar() 必定是 function
  • -1 會是 EOF 或 Error

int putc(int c, FILE *fp); int fputc(int c, FILE *fp); int putchar(int c);

  • putc() 有可能是 macro, putchar() 必定是 function

char *fgets(char *buf, int n, FILE *fp);

  • \0 才會停下,\n 會被讀入

char *gets(char *buf);

  • 沒有指定 buffer size,會 overflow.

char *fputs(const char *str, FILE *fp); char *puts(const char *str);

  • 一個一個 string 寫入 terminal,沒有 overflow 的問題

size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp); size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);

  • Binary I/O
  • 可以一個一個 Object 寫入
  • struct {
        short count;
        long total;
        char name[NAME_SIZE];
    } item;
    if (fwrite(&item, sizeof(item), fp) != 1)
        err_sys("fwrite error");
    c

Input Functions:

  • int scanf(const char *format, …);
  • int fscanf(FILE *fp, const char *format, …);
  • int sscanf(char *buf, const char *format, …);

Output Functions:

  • int printf(const char *format, …);
  • int fprintf(FILE *fp, const char *format, …);
  • int sprintf(char *buf, const char *format, …); Overflow is possible for sprintf() –
  • ‘\0’ appended at the end of the string. A better substitute: snprintf()
  • int vprintf(const char *format, va_list arg);
  • int vfprintf(FILE *fp, const char *format, va_list arg);
  • int vsprintf(char *buf, const char *format, va_list arg);

Standard I/O Performance#

FunctionUser CPU (s)System CPU (s)Clock Time (s)Bytes of Program Text
Best time using read/write0.010.186.67
fgets, fputs2.590.197.15139
getc, putc10.840.2712.07120
fgetc, fputc10.440.2711.42120
Single byte using read/write124.89161.65288.64
  • 真正用 System CPU 的時間,Best use 跟其他 Standard Library 的其實一樣
    • Standard library 是在節省 System CPU time

int fwide(FILE *fp, int mode)

  • Standard I/O in C lib 會有 orientation
    • single byte character
    • multiple byte character
  • 一但被 set 就不能 reset

Back to the content

NTU PJ System Programming

2025 Fall

← Back to the content


NTU-SP 系統程式設計 Ch4 Buffered I/O
https://vinsong.csie.org/blog/ntu-sp-ch04-bufio
Author VinSong
Published at 2025年11月30日