linux文件IO与内存映射:用户空间的IO缓冲区
生活随笔
收集整理的這篇文章主要介紹了
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
};
其中重要的數據結構為:
int _fileno;我們的文件描述符char *_IO_buf_base;IO緩沖區的起始區域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 bufferedsize緩沖區內字節數
代碼如下:
#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缓冲区的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 绝对性不孕症
- 下一篇: linux文件IO与内存映射:分散/聚集