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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

淘宝文件系统文件映射原理及实现

發布時間:2025/4/5 windows 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 淘宝文件系统文件映射原理及实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1 文件系統映射原理
      • 1.1 文件映射應用場景
      • 1.2 文件映射相關函數介紹
    • 2 文件映射實戰

1 文件系統映射原理

1.1 文件映射應用場景

主要應用場景如下:

  • 進程間共享信息。
  • 實現文件數據從磁盤到內存的映射,極大的提升應用程序訪問文件的速度。

1.2 文件映射相關函數介紹

作用:將一個文件或者其它對象映射進內存。

  • 使用普通文件提供的內存映射。
  • 使用特殊文件提供匿名內存映射。

  • mmap函數:

    #include <sys/mman.h>void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);int munmap(void *addr, size_t length); /* 參數start:指向欲映射的內存起始地址,通常設為 NULL,代表讓系統自動選定地址,映射成功后返回該地址。參數length:代表將文件中多大的部分映射到內存。參數prot:映射區域的保護方式。可以為以下幾種方式的組合:PROT_EXEC 執行 PROT_READ 讀取 PROT_WRITE 寫入 PROT_NONE 不能存取參數flags:影響映射區域的各種特性。必須要指定MAP_SHARED 或MAP_PRIVATE。MAP_SHARED - 映射區域數據與文件對應,允許其他進程共享MAP_PRIVATE - 映射區域生成文件的copy,修改不同步文件MAP_ANONYMOUS - 建立匿名映射。此時會忽略參數fd,不涉及文件,而且映射區域無法和其他進程共享。MAP_DENYWRITE - 允許對映射區域的寫入操作,其他對文件直接寫入的操作將會被拒絕。MAP_LOCKED - 將映射區域鎖定住,這表示該區域不會被置swap參數fd:要映射到內存中的文件描述符。如果使用匿名內存映射時,即flags中設置了MAP_ANONYMOUS,fd設為-1。有些系統不支持匿名內存映射,則可以使用fopen打開/dev/zero文件,然后對該文件進行映射,可以同樣達到匿名內存映射的效果。參數offset:文件映射的偏移量,通常設置為0,代表從文件最前方開始對應,offset必須是分頁大小的整數倍(分頁大小一般是4KB)。  */

    msync函數介紹:
    實現磁盤文件內容于共享內存區中的內容一致,即同步操作。

    //函數原型 int msync ( void * addr, size_t len, int flags) //頭文件 #include<sys/mman.h> /* addr:文件映射到進程空間的地址; len:映射空間的大小; flags:刷新的參數設置,可以取值MS_ASYNC/ MS_SYNC 其中:取值為MS_ASYNC(異步)時,調用會立即返回,不等到更新的完成;取值為MS_SYNC(同步)時,調用會等到更新完成之后返回;返回值:成功則返回0;失敗則返回-1; */

    mremap函數介紹:
    擴大(或縮小)現有的內存映射。

    //函數原型 void * mremap(void *old_address, size_t old_size , size_t new_size, int flags);//頭文件 #include <unistd.h> #include <sys/mman.h>/* addr: 上一次已映射到進程空間的地址; old_size: 舊空間的大小; new_size: 重新映射指定的新空間大小; flags: 取值可以是0或者MREMAP_MAYMOVE,0代表不允許內核移動映射區域,MREMAP_MAYMOVE則表示內核可以根據實際情況移動映射區域以找到一個符合new_size大小要求的內存區域返回值:成功則返回映射后內存區域的地址,失敗則返回(void*)-1; */

    2 文件映射實戰

    主要由map_file.cpp、map_file.h、common.h、main.cpp幾個文件。

    common.h:

    #ifndef _COMMON_H_INCLUDED_ #define _COMMON_H_INCLUDED_#include <iostream> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <string> #include <string.h> #include <stdint.h> #include <inttypes.h> #include <errno.h> #include <stdio.h> #include <sys/mman.h> #include <unistd.h> #include <stdlib.h> #include <assert.h>#endif /*_COMMON_H_INCLUDED_*/

    map_file.h:

    #ifndef QINIU_LARGEFILE_MMAPFILE_H_ #define QINIU_LARGEFILE_MMAPFILE_H_#include <unistd.h> #include "common.h"namespace qiniu {namespace largefile{class MMapFile{public:MMapFile();explicit MMapFile(const int fd);MMapFile(const MMapOption& mmap_option, const int fd);~MMapFile();bool sync_file(); //同步內存數據到文件bool map_file(const bool write = false); //將文件映射到內存,同時設置訪問權限void *get_data() const ; //獲取映射到內存數據的首地址int32_t get_size() const; //獲取映射數據的大小bool munmap_file(); //解除映射bool remap_file(); //重新執行映射 mremapprivate:bool ensure_file_size(const int32_t size);private:int32_t size_;int fd_;void *data_;struct MMapOption mmap_file_option_; };}}#endif //

    map_file.cpp:

    #include "mmap_file.h" #include <stdio.h>static int debug = 1;namespace qiniu {namespace largefile{MMapFile::MMapFile():size_(0), fd_(-1), data_(NULL){}MMapFile::MMapFile(const int fd):size_(0), fd_(fd), data_(NULL){}MMapFile::MMapFile(const MMapOption& mmap_option, const int fd):size_(0), fd_(fd), data_(NULL){mmap_file_option_.max_mmap_size_ = mmap_option.max_mmap_size_;mmap_file_option_.first_mmap_size_ = mmap_option.first_mmap_size_;mmap_file_option_.per_mmap_size_ = mmap_option.per_mmap_size_;}MMapFile::~MMapFile(){if(data_){if(debug) printf("mmap file destruct, fd: %d, maped size: %d, data: %p\n", fd_, size_, data_);msync(data_, size_, MS_SYNC);munmap(data_, size_);size_ = 0;data_ = NULL;fd_ = -1;mmap_file_option_.max_mmap_size_ = 0;mmap_file_option_.first_mmap_size_ = 0;mmap_file_option_.per_mmap_size_ = 0;}}bool MMapFile::sync_file(){if(NULL !=data_ && size_ > 0){return msync(data_, size_, MS_ASYNC)==0;}return true;}bool MMapFile::map_file(const bool write ){int flags = PROT_READ;if(write){flags |= PROT_WRITE;}if(fd_<0){return false;}if(0 == mmap_file_option_.max_mmap_size_){return false;}if(size_<mmap_file_option_.max_mmap_size_){size_ = mmap_file_option_.first_mmap_size_;}else {size_ = mmap_file_option_.max_mmap_size_;}if(!ensure_file_size(size_)){fprintf(stderr, "ensure file size failed in map_file , size : %d\n", size_);return false; }data_ = mmap(0, size_, flags, MAP_SHARED, fd_, 0);if(MAP_FAILED == data_){fprintf(stderr, "map file failed: %s\n", strerror(errno));size_ = 0;fd_ = -1;data_ = NULL;return false;}if(debug) printf("mmap file successed, fd: %d maped size: %d, data: %p\n", fd_, size_, data_);return true;}void *MMapFile::get_data() const {return data_;}int32_t MMapFile::get_size() const{return size_;}bool MMapFile::munmap_file(){if(munmap(data_, size_)==0){return true;}else {return false;}}bool MMapFile::ensure_file_size(const int32_t size){struct stat s;if(fstat(fd_, &s) < 0){fprintf(stderr, "fstat error, error desc: %s\n", strerror(errno));return false;}if(s.st_size < size){if(ftruncate(fd_, size) < 0){fprintf(stderr, "ftruncate error, size: %d, error desc: %s\n", size, strerror(errno));return false;}}return true; }bool MMapFile::remap_file(){//1. 防御性編程if(fd_ < 0 || data_ == NULL){fprintf(stderr, "mremap not mapped yet\n");return false;}if(size_ == mmap_file_option_.max_mmap_size_){fprintf(stderr, "already mapped max size, now size: %d, max size: %d\n", size_, mmap_file_option_.max_mmap_size_);return false;}int32_t new_size = size_+ mmap_file_option_.per_mmap_size_;if(new_size > mmap_file_option_.max_mmap_size_){new_size = mmap_file_option_.max_mmap_size_;}if(!ensure_file_size(new_size)){fprintf(stderr, "ensure file size failed in remap_file , size : %d\n", new_size);return false; }if(debug) printf("mremap start. fd: %d, now size: %d, new size: %d, old data: %p\n", fd_, size_, new_size, data_);void *new_map_data = mremap(data_, size_, new_size, MREMAP_MAYMOVE);if(MAP_FAILED == new_map_data){fprintf(stderr, "mremap failed , fd: %d, new size: %d, error desc: %s\n", fd_, new_size, strerror(errno));return false;}else {if(debug) printf("mremap success. fd: %d, now size: %d, new size: %d, old data: %p, new data: %p\n", fd_, size_, new_size,data_, new_map_data);}data_ = new_map_data;size_ = new_size;return true;}} }

    main.cpp:

    #include "mmap_file.h" #include "common.h"using namespace std; using namespace qiniu;static const mode_t OPEN_MODE = 0644; const static largefile::MMapOption mmap_option={10240000, 4096, 4096}; //內存映射的參數int open_file(string file_name, int open_flags){int fd = open(file_name.c_str(), open_flags, OPEN_MODE); //open 成功返回的一定是>0if(fd < 0){return -errno; //errno strerror(errno); //read errno}return fd;}int main(void ){const char *filename = "./mapfile_test.txt";//1. 打開/創建一個文件,取得文件的句柄 open函數int fd = open_file(filename, O_RDWR | O_LARGEFILE);if(fd<0){//調用read ,出錯重置 errno fprintf(stderr, "open file failed. filename:%s, error desc: %s\n", filename, strerror(-fd));return -1;}largefile::MMapFile *map_file = new largefile::MMapFile(mmap_option, fd);bool is_mapped = map_file->map_file(true);if(is_mapped){map_file->remap_file();memset(map_file->get_data(), '9', map_file->get_size());map_file->sync_file();map_file->munmap_file();}else {fprintf(stderr, "map file failed\n");}delete map_file;close(fd);return 0; }

    參考資料:

  • C/C++從入門到精通-高級程序員之路【奇牛學院】
  • 總結

    以上是生活随笔為你收集整理的淘宝文件系统文件映射原理及实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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