完整的源码在下面这个链接哟
github源码
哈希链表结构
哈希表 - 散列表 它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法 关键点:- 键(key): 文件的编号 如, 1 、 5 、 19 。 。 。
- 值(value): 文件的索引信息(包含 文件大小、位置)
- 索引: 数组的下标(0,1,2,3,4) ,用以快速定位和检索数据
- 哈希桶: 保存索引的数组,数组成员为每一个索引值相同的多个元素(以链表的形式链接)的首节点
- 哈希函数: 将文件编号映射到索引上(把key映射到索引),采用求余法 ,如: 文件编号 19 就取余19%k(k为哈希桶的大小)
说明:像我们的上面的例子,如果是把0~19放在一个链表中,如果我们要找某个元素那么可能我们最多要一个一个找最多要搜寻20次,而如果我们利用哈希映射那么我们最多只要搜寻4次(这还是我们把哈希桶的大小取为5的情况,如果是取为10那么最多只要搜寻两次)
内存映射
应用场景
1.进程间共享信息 2.实现文件数据从磁盘到内存的映射,极大的提升应用程序访问文件的速度进程间通信 - 文件映射原理(mmap函数)
原理:将一个文件或者其它对象映射进内存。 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:代表将文件中多大的部分映射到内存(是页的整数倍(x86系列的是一页4096字节为4KB))。
参数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(同步)时,调用会等到更新完成之后返回;
内存映射之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大小要求的内存区域
返回值
成功则返回0;失败则返回-1;