淘宝文件系统文件映射原理及实现
生活随笔
收集整理的這篇文章主要介紹了
淘宝文件系统文件映射原理及实现
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 1 文件系統(tǒng)映射原理
- 1.1 文件映射應(yīng)用場(chǎng)景
- 1.2 文件映射相關(guān)函數(shù)介紹
- 2 文件映射實(shí)戰(zhàn)
1 文件系統(tǒng)映射原理
1.1 文件映射應(yīng)用場(chǎng)景
主要應(yīng)用場(chǎng)景如下:
- 進(jìn)程間共享信息。
- 實(shí)現(xiàn)文件數(shù)據(jù)從磁盤到內(nèi)存的映射,極大的提升應(yīng)用程序訪問文件的速度。
1.2 文件映射相關(guān)函數(shù)介紹
作用:將一個(gè)文件或者其它對(duì)象映射進(jìn)內(nèi)存。
mmap函數(shù):
msync函數(shù)介紹:
實(shí)現(xiàn)磁盤文件內(nèi)容于共享內(nèi)存區(qū)中的內(nèi)容一致,即同步操作。
mremap函數(shù)介紹:
擴(kuò)大(或縮小)現(xiàn)有的內(nèi)存映射。
2 文件映射實(shí)戰(zhàn)
主要由map_file.cpp、map_file.h、common.h、main.cpp幾個(gè)文件。
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(); //同步內(nèi)存數(shù)據(jù)到文件bool map_file(const bool write = false); //將文件映射到內(nèi)存,同時(shí)設(shè)置訪問權(quán)限void *get_data() const ; //獲取映射到內(nèi)存數(shù)據(jù)的首地址int32_t get_size() const; //獲取映射數(shù)據(jù)的大小bool munmap_file(); //解除映射bool remap_file(); //重新執(zhí)行映射 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}; //內(nèi)存映射的參數(shù)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. 打開/創(chuàng)建一個(gè)文件,取得文件的句柄 open函數(shù)int fd = open_file(filename, O_RDWR | O_LARGEFILE);if(fd<0){//調(diào)用read ,出錯(cuò)重置 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; }參考資料:
總結(jié)
以上是生活随笔為你收集整理的淘宝文件系统文件映射原理及实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有妖气是什么公司 最近被B站重金收购
- 下一篇: 将服务端移植到Linux和MAC OS