開源高頻交易系統(tǒng)Kungfu的代碼解析(1)
從util的源碼開始學(xué)習(xí),主要從mmap 和 signal 這兩部分,涉及的知識是關(guān)于ipc 和 信號方面的。先從mmap 開始。
背景:功夫的核心通信機(jī)制是MMAP,本篇來解讀一下這一部分。
共享內(nèi)存:非血緣關(guān)系進(jìn)程間的一種通信方式
回顧一下mmap函數(shù):
void *mmap(void *adrr, size_t length, int prot, int flags, int fd, off_t offset);
返回:成功:返回創(chuàng)建的映射區(qū)首地址;失?。?/b>MAP_FAILED宏
參數(shù):????
???????? addr:????? 建立映射區(qū)的首地址,由Linux內(nèi)核指定。使用時,直接傳遞NULL
???????? length:欲創(chuàng)建映射區(qū)的大小
???????? prot:????? 映射區(qū)權(quán)限PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE
???????? flags:???? 標(biāo)志位參數(shù)(常用于設(shè)定更新物理區(qū)域、設(shè)置共享、創(chuàng)建匿名映射區(qū))
?????????????????? ? ???? MAP_SHARED:?會將映射區(qū)所做的操作反映到物理設(shè)備(磁盤)上。
?????????????????? ? ???? MAP_PRIVATE:映射區(qū)所做的修改不會反映到物理設(shè)備。
???????? fd:??????? 用來建立映射區(qū)的文件描述符
???????? offset: 映射文件的偏移(4k的整數(shù)倍)
再看一下功夫的代碼
mmap 在功夫中創(chuàng)建映射區(qū)的代碼:kungfu/core/cpp/yijinjing/src/util/mmap.cpp
????????????????bool master = is_writing || !lazy;
? ? ? ? ? ? ? ? int fd = open(path.c_str(), (master ? O_RDWR : O_RDONLY) | O_CREAT, (mode_t) 0600);?
? ? ? ? ? ? ? ? //文件描述符fd ,讀寫權(quán)限判斷,如果master為真,表明正在寫,則文件權(quán)限為只讀;0600 權(quán)限設(shè)置
? ? ? ? ? ? ? ? if (fd < 0)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? throw journal_error("failed to open file for page " + path);
? ? ? ? ? ? ? ? //這里journal 是他定義的寫入單元,每次 mmap 創(chuàng)建的文件為 Journal 的一個頁(Page)
? ? ? ? ? ? ?? }
? ? ? ? ? ? ? ? if (master)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? if (lseek(fd, size - 1, SEEK_SET) == -1)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? ? ? ? ? throw journal_error("failed to stretch for page " + path);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? if (write(fd, "", 1) == -1)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? ? ? ? ? throw journal_error("unable to write for page " + path);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? /**
? ? ? ? ? ? ? ? * MAP_FIXED is dup2 for memory mappings, and it's useful in exactly the same situations where dup2 is useful for file descriptors:
? ? ? ? ? ? ? ? * when you want to perform a replace operation that atomically reassigns a resource identifier (memory range in the case of MAP_FIXED,
? ? ? ? ? ? ? ? * or fd in the case of dup2) to refer to a new resource without the possibility of races where it might get reassigned to something
? ? ? ? ? ? ? ? * else if you first released the old resource then attempted to regain it for the new resource.
? ? ? ? ? ? ? ? */
? ? ? ? ? ? ? ? void *buffer = mmap(0, size, master ? (PROT_READ | PROT_WRITE) : PROT_READ, MAP_SHARED, fd, 0);
? ? ? ? ? ? ? ? // mmap 創(chuàng)建映射區(qū)
? ? ? ? ? ? ? ? if (buffer == MAP_FAILED)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? ? ? throw journal_error("Error mapping file to buffer");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (!lazy && madvise(buffer, size, MADV_RANDOM) != 0 && mlock(buffer, size) != 0)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? munmap(buffer, size);
? ? ? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? ? ? throw journal_error("failed to lock memory for page " + path);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? close(fd);