linux的内存管理介绍
内存方面的知识真是博大精深,把一些看到的零碎的知识点做个笔记总结下。
这些知识只是自己的理解,并不能保证正确,ULK和《深入理解Linux虚拟内存管理》这两本书看完以后还会来更新这篇的内容。
段式管理与页式管理
在操作系统理论中
内存方面的知识真是博大精深,把一些看到的零碎的知识点做个笔记总结下。
这些知识只是自己的理解,并不能保证正确,ULK和《深入理解Linux虚拟内存管理》这两本书看完以后还会来更新这篇的内容。
在操作系统理论中
内存管理有两篇文章讲的还是满清晰的:
The Linux Kernel-Chapter 3 Memory Management
下面这本书是有不少中文翻译的,可以自行查找
本文主要是讨论伙伴算法的,讲伙伴算法的文章虽然多,但是没几篇讲的很清楚的。我也是结合了几篇文章看了好久才弄明白,特地记下来。
业务线上出错,返回给用户的结果不正确。
使用了ZINTERSTORE这个接口对多个集合做交并集返回预期外的空集。如下图:
这是因为twemproxy只是把指令转发给redis而已,而多个集合被哈希算法分片在不同的redis节点上,所以转发这个redis并没有这几个集合,会直接返回空集。
这并不是BUG,redis3.0也存在这个特性,当多个集合做交并集操作时,需要使用hash_tag特性。
由于twemproxy的多进程改造计划,所以对教科书一般的nginx的管理方式做了分析
nginx的-s指令可以对进程执行多个命令。
这些命令由主进程接受信号然后在循环中对状态进行判断,然后通过unix socket或者信号的方式传达给子进程。
从代码里面可以看到如下状态。
1 | for() |
twemproxy的多进程改造计划中参考了nginx的设计,然而nginx有一段让我看不太明白。
这篇文章总结的很好
sigsuspend将新的信号集阻塞操作和pause操作组合在一起成为原子操作
做了以下的操作
nginx的文件缓存分为两种,内存缓存和硬盘缓存。
内存缓存指文件句柄等信息进行缓存,减少使用open等的系统调用。
硬盘缓存指文件被缓存到硬盘上,一般是因为当作反向代理用才会有这种需求。
内存缓存是全模块都可以调用的,因为封装在core/ngx_open_file_cache.c中。
而硬盘缓存只有http模块可以调用,因为封装在http/ngx_http_file_cache.c中,最常见的就是upstream模块的cache了。
C的内存管理难已经成为了共识。记得我那时候写ydfs,第一次接触全异步编程这种模式,没有考虑到内存的统一管理,导致溢出泄漏问题层出不穷。最终搞定没BUG了,那代码的阅读质量也是让人不敢恭维。那么来看看nginx是怎么做的吧。
nginx的内存池分为池(pool)和块(block)两个概念
这是nginx使用到的内存结构
1 | typedef struct ngx_pool_large_s ngx_pool_large_t; |
池中以链表的形式保存许多块以及large链表。这是从数据结构中能大致看出的东西。
nginx把整个时间的系统调用都封装了一遍。
其中有两个原因
1 不谈其他平台,至少在linux上,很多时间相关的系统调用不是async-signal-safe或thread-safe的。
例如local_time_r虽然是thread-safe的但不是async-signal-safe的,当然local_time两个都不是。