日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

linux文件IO与内存映射:用户空间的IO缓冲区

發布時間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux文件IO与内存映射:用户空间的IO缓冲区 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • 用戶空間IO緩沖區產生
        • IO緩沖區 描述
        • IO緩沖區的寫模式
        • 自定義IO緩沖區

用戶空間IO緩沖區產生

系統調用過程中會產生的開銷如下:

  • 切換CPU到內核態
  • 進行數據內容的拷貝,從用戶態到內核態或者從內核態到用戶態
  • 切換CPU到用戶態

以上為普通到系統調用過程中操作系統需要產生的額外開銷,為了提升系統調用的性能,這里推出用戶空間的IO緩沖區,即文件讀寫在用戶空間時寫入IO緩沖區,后續的寫入或者讀出page cache則直接由IO緩沖區進行讀寫。

IO緩沖區所處操作系統位置如下圖:

IO緩沖區 描述

C標準庫創建的IO緩沖區

  • 在用戶空間,為每個打開的文件分配一個I/O緩沖區、分配一個文件描述符、I/O緩沖區信息和文件描述符一起封裝在FIFE結構體中
  • size_t fread(void *ptr,size_t size,size_t memb,FILE *stream);
  • size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

關于FILE結構體的內容如下/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h

/* The tag name of this struct is _IO_FILE to preserve historicC++ mangled names for functions taking FILE* arguments.That name should not be used in new code.  */
struct _IO_FILE
{int _flags;		/* High-order word is _IO_MAGIC; rest is flags. *//* The following pointers correspond to the C++ streambuf protocol. */char *_IO_read_ptr;	/* Current read pointer */char *_IO_read_end;	/* End of get area. */char *_IO_read_base;	/* Start of putback+get area. */char *_IO_write_base;	/* Start of put area. */char *_IO_write_ptr;	/* Current put pointer. */char *_IO_write_end;	/* End of put area. */char *_IO_buf_base;	/* Start of reserve area. */char *_IO_buf_end;	/* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base;  /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno;int _flags2;__off_t _old_offset; /* This used to be _offset but it's too small.  *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

其中重要的數據結構為:

  1. int _fileno;我們的文件描述符
  2. char *_IO_buf_base; IO緩沖區的起始區域
  3. char *_IO_buf_end; IO緩沖區的結束區域

當使用fread進行讀文件時

  • 打開文件,獲取到文件描述符_fileno
  • 利用文件描述符獲取到文件inode,根據文件inode先到io緩沖區中獲取當前文件內容,如果獲取不到則執行下一步,否則直接返回。
  • 根據文件inode從page cache中獲取到對應的緩存頁的內容
  • 將獲取到的內容讀到讀的IO緩沖區

當使用fwrite寫文件時

  • 打開文件,獲取到文件描述符
  • 利用文件描述符獲取到文件inode,將需要寫到內容寫入到io緩沖區中
  • io緩沖區利用fflush將其中到內容寫入到page cache頁高速緩沖區中
  • 再由page cache根據是否達到閾值,將page cache中的數據pdflush回寫到磁盤中

IO緩沖區的寫模式

使用fwrite寫文件時的第二步 IO 緩沖區中的數據fflush到page cache時有幾種不同的寫模式,即根據不同的模式將IO緩沖區的數據寫入到page cache中。

  • 塊緩沖(block buffered):
    固定字節的緩沖區大小,比如跟文件相關的流都是塊緩沖
    標準IO塊緩沖為完全緩沖(full bufferring)
    此時,當客戶端將塊緩沖區寫滿之后,才會向page cache中下刷數據,一般的文件操作都為塊緩沖區
  • 行緩沖(line buffered):
    遇到換行符,緩沖區中的數據會拷貝到內核緩沖區
  • 無緩沖(unbuffered)
    數據直接拷貝到內核緩沖區
    如:標準錯誤stderr采用無緩沖模式

自定義IO緩沖區

系統默認開辟的IO緩沖區大小為8K,但是很多時候我們需要寫入文件內容是大于8K,這個時候需要我們自定義IO緩沖區大小,使用如下C庫函數:

  • 頭文件 <stdio.h>
  • 函數使用:
    void setbuf(FILE *stream, char *buf); //無緩沖區
    void setbuffer(FILE *stream, char *buf, size_t size);//塊緩沖區
    void setlinebuf(FILE *stream);//行緩沖區//兼容三種緩沖期	
    int setvbuf(FILE *stream, char *buf, int mode, size_t size);
    
  • 參數描述:
    • stream 指向流的指針
    • buf 緩沖區地址
    • mode緩沖區類型
      如下三種
      _IONBF //無unbuffered
      _IOLBF //行line buffered
      _IOFBF //塊fully buffered
      
    • size 緩沖區內字節數

代碼如下:

#include <stdio.h>int main() {char buf[BUFSIZ];char buf2[BUFSIZ];//printf("BUFSIZ is %d\n",BUFSIZ);setvbuf(stdout,buf,_IOFBF,BUFSIZ);printf("BUFSIZ after setvbuf is %d\n",BUFSIZ);setbuffer(stdout, buf2,10240);printf("hello world\n");printf("buf:%s\n",buf);printf("buf2:%s\n",buf2);return 0;
}

總結

以上是生活随笔為你收集整理的linux文件IO与内存映射:用户空间的IO缓冲区的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。