面试总喜欢被问Redis是单线程还是多线程,千篇一律的回答单线程却不知所以然,严格来说Redis是多线程多进程、单线程处理请求,本文说的就是多线程下的BIO(Background I/O service)。
【Redis源码分析】Redis启动过程是这样的!
redis的源码确实是比我想象中要好读,本身是过程式编程,所以很多核心逻辑已经包含在main函数的调用链,流程非常长,耐心看下去还是能get到些东西的。
【网络编程】从Linux角度以及JVM源码,深入NIO的细节
最近一段时间都在啃Linux内核, 也给了自己机会再度深入理解Java的NIO实现,希望能获得更多东西,尝试理解以前未能理解的,会涉及少量OpenJDK源码。
因为NIO本身的实现很多牵扯到操作系统,所以需要先稍微过一下,有理解不对的地方,请指出。
1、涉及的Linux知识
1.1、文件描述符
对于Linux来说,一切皆为文件,设备文件、IO文件还是普通文件,都可以通过一个叫做文件描述符(FileDescriptor)的东西来进行操作,其涉及的数据结构可以自行了解VFS。
1.1.1、设备阻塞与非阻塞
任意对设备的操作都是默认为阻塞的,如果没有或有不可操作的资源,会被添加到wait_queue_head_t
中进行等待,直到被semaphore
通知允许执行。此时可以通过fcntl()
函数将文件描述符设置为非阻塞,若没有或有不可操作的资源,立即返回错误信息。
1.2、JVM内存结构 & 虚拟地址空间
众所周知,Linux下的每一进程都有自己的虚拟内存地址,而JVM也是一个进程,且JVM有自己的内存结构。既然如此,两者之间必有对应关系,OracleJDK7提供了NMT,用jcmd pid VM.native_memory detail
可以查看各类区域的reserved,被committed的内存大小及其地址区间,再通过pmap -p
可以看到进程内存信息。
肉眼对比地址区间可以发现,JVM heap是通过mmap分配内存的,位于进程的映射区内,而进程堆区可以被malloc进行分配,对应关系如图。