服务器架构设计5------通过共享内存实现0拷贝

前几篇文章,分别聊了linux的磁盘技术、cpu进程调度,还剩下内存没怎么研究,今天来聊聊服务器内存的0拷贝。

linux服务器,特别类似于流媒体服务器,往往涉及到大数据量的输入、分析、输出,那么一旦运用了多进程,难免会出现多进程对公共内存共享的问题,不用说,共享内存的应用就产生了。

本篇文章不会涉及太多code层次的问题,仅从design层次给出大体的方法。


把问题抽象一下,就是n个进程,需要对一大块共享内存做操作,这就涉及几个关键点。

  1. 分配内存池;
  2. 内存池的管理,包括内存的分配、内存的释放、多个进程对内存池分配释放的同步;
  3. 如何保证内存首地址的传递,读写同步问题。
下面一个一个说。

一、分配内存

共享内存,分配内存的方法shmget,可以控制多个进程的启动顺序,同时内存分配之后,通过函数shmctl将SHM_LOCK置上,防止将共享内存swap到磁盘上去,如果共享内存swap到磁盘,当某个进程需要访问该块内存,就会被堵塞住,系统需要将内存从磁盘swap回内存,进程才能访问,这是很影响性能的一个操作,所以要注意。

二、内存池的管理

谈到内存池的管理,方法很多,如果每次申请的内存是一边大的,可以预先划好几块内存,如果不一边大,也可以事先构造一些内存链表,每种链表代表不同大小的内存,每次分配都从这链表中找。今天给出一种我用过的,分配内存的大小可以不一致(当然一致,性能会更好些)。

数据结构:

struct mempool {
	size_t mp_size; // mempool total size
	size_t mp_offset; // used memory offset
	mem_chunk mp_free_chunk; // free chunk list 
};
struct mem_chunk {
	size_t mc_size; // 字节对齐之后的大小
	size_t mc_usize; // 用户请求的内存大小,如果用户请求3个字节,则实际分配4个字节。
	union mem_chunk_mc_u;			
};
union mem_chunk_mc_u {
	struct mem_chunk * mc_next; // 用于释放内存构造链表指针
	char * mc_cp; // 用于malloc,返回给用户的指针地址
};

内存分配释放图示:


总体思想:

  1. 总内存最开头,mempool,信息包括总内存大小,已使用内存offset,已释放内存chunk list

  2. 申请过程:以chunk为单位,每块内存前多分配两个size大小,2个size之后的内存ptr返回给用户用,申请过程先从free chunk list中找,有则返回,实在没有再到后面划分内存来

  3. 释放过程,在mempool保存了释放chunk的一个链表,mc_usize同时用于mempool中的释放内存chunk链表节点计数,没多一个节点则+1,注意相邻内存是要合并的。

内存分配释放同步机制:可以采用信号量,在分配和释放上,做同步互斥用,具体方法可以参见


三、内存同步管理

内存如何进行同步管理:构造内存结构体,包括优先级、引用计数、内存指针、内存大小,将结构体insert到db数据库,对内存的使用,分为open和close,open时引用计数+1,close时引用计数-1。同时需要保证,仅有一个进程对书库进行写操作,其它进程只有读操作。专门启动一进程,用于内存管理,可以周期性的检查,当引用计数为0,直接从数据库中删除,同时释放内存。

那么db数据库有那些选择呢,Berkeley_DB, leveldb


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值