云计算百科
云计算领域专业知识百科平台

如果保证pkt申请到内存

    在推流拉流的过程中,我们是一帧一帧推的,那这一帧的数据保存在堆里,每一帧大小从几十 KB 到几百 KB,如果我们用C库提供的malloc和free,极易产生内存碎片。
而且嵌入式设备最缺的之一就是内存,所以我们要避免内存碎片,还要保证在内存紧张的时候,还能申请到pkt。所以有了双堆系统:
    pkt 不宜直接走通用 malloc。需要先向系统要大块堆,平时只在堆里拆给 pkt,避开高频进出内核,也减少碎片。可是只有一片堆时,新问题马上出现:释放的块立刻被下一个 pkt 拿走,这片堆很难空,高峰配上的物理页还是退不下去。于是用两片堆,做成双池,同一时刻只让一片接新的 pkt。接新申请的叫热池。pkt 都从热池拆。热池满了,并不把这片映射拆掉,而是把「热」标到另一片上。之后新 pkt 只从新热池出。原来那片变成冷池:只出不进。冷池里的 pkt 陆续释放后,空洞不会被马上填回去,这才具备把物理页还给系统的条件。业务不用停,只是换一片堆继续拆。两片堆的虚拟地址会一直留着。真正和别的模块抢的是底下的物理页。所以回收针对页,而不是把整池从进程里卸掉:告诉内核这些足够大的整页近期不用了,页框可以给别人;地址还在,下次高峰不必重新向系统要一整片堆。以后若再写到这些地址,再重新缺页即可。不是释放多少就还多少。页有粒度,头尾还要留管理信息,只能还中间对齐好的整页。太小的洞还了,热路径马上又要,会变成不停缺页。因此冷池可以更积极地还(大约 16KB 以上的空洞),因为它已经不接新 pkt;热池还要继续拆块,门槛更高(大约 64KB),避免刚还又要。更小的碎片留在池里拼,拼出整页再还。还在使用的 pkt,页当然不能动。切池那一刻,也只整理旧池里已经空闲、并且够大的洞,不会去动还没释放的包。两片来回切:一边继续给 pkt 供数,一边让刚满过的那片有机会瘦身。这样,pkt 不再每次打扰通用分配器,高峰过后常驻内存有机会掉下来,堆的地址又不必反复向系统要。它解决的是「申请要快、峰值能回落」,不是「任意一次释放都立刻退光内存」。若冷池里的包一直被人拿着,页照样还不回去。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 如果保证pkt申请到内存
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!