linux 内存篇

持续更新...

现代的CPU包含了自动把虚拟地址转换成物理地址的硬件电路

所有的UNIX操作系统都将RAM划分为两部分:

1. 第一部分:若干兆字节专门用于存放内核映像(内核代码+内核静态数据)

2. 第二部分用于:

      a.  满足内核对缓冲区、描述符和其他动态内核数据结构的请求

      b. 满足进程对一般内存区的请求及对文件内存映射的请求

      c.  借助于高速缓存从磁盘及其他缓冲设备获得较好的性能

 

内核内存分配器(Kernel Memory Allocator, KMA)

基于各种不用的算法技术,已经存在几种KMA

1. 资源图分配算法

2. 2的幂次方空闲链表

3. McKusick-Karels分配算法

4. Buddy System

5. Mach的zone 分配算法

6. Dynix分配算法

7. Solaris的Slab分配算法

Linux 的KMA是Buddy System之上采用slab分配算法

 

所有现代的UNIX操作系统都采用了请求调页的内存分配策略。进程可以在它的页还没有在物理内存时就开始执行。当进程访问一个不存在的页时,MMU产生一个异常;

异常处理程序找到受影响的内存区,分配一个空闲的页,并用适当的数据把它初始化。

同理,当进程通过malloc( )或brk( )(malloc内部调用brk)动态地请求内存时,内核仅仅修改进程堆内存区的大小。只有试图引用进程的虚拟内存地址而产生异常时,才给进程分配页框。

 

Linux 进程虚拟内存查看:

1. cat /proc/$pid/statm (查看到的数值是以PAGE为单位,top看到的值是以KB为单位

2. cat /proc/$pid/maps (也可以使用pmap工具查看)

08048000-08053000 r-xp 00000000 08:08 6291541    /bin/cat
08053000-08054000 r--p 0000a000 08:08 6291541    /bin/cat
08054000-08055000 rw-p 0000b000 08:08 6291541    /bin/cat
0839b000-083bc000 rw-p 00000000 00:00 0          [heap]
b7224000-b7394000 r--p 001bc000 08:07 3676427    /usr/lib/locale/locale-archive
b7394000-b7594000 r--p 00000000 08:07 3676427    /usr/lib/locale/locale-archive
b7594000-b7595000 rw-p 00000000 00:00 0 
b7595000-b773d000 r-xp 00000000 08:08 1049593    /lib/i386-linux-gnu/libc-2.19.so
b773d000-b773f000 r--p 001a8000 08:08 1049593    /lib/i386-linux-gnu/libc-2.19.so
b773f000-b7740000 rw-p 001aa000 08:08 1049593    /lib/i386-linux-gnu/libc-2.19.so
b7740000-b7743000 rw-p 00000000 00:00 0 
b775c000-b775d000 r--p 00855000 08:07 3676427    /usr/lib/locale/locale-archive
b775d000-b775f000 rw-p 00000000 00:00 0 
b775f000-b7760000 r-xp 00000000 00:00 0          [vdso]
b7760000-b7780000 r-xp 00000000 08:08 1049595    /lib/i386-linux-gnu/ld-2.19.so
b7780000-b7781000 r--p 0001f000 08:08 1049595    /lib/i386-linux-gnu/ld-2.19.so
b7781000-b7782000 rw-p 00020000 08:08 1049595    /lib/i386-linux-gnu/ld-2.19.so
bff09000-bff2a000 rw-p 00000000 00:00 0          [stack]

第三列是映射文件地址偏移(mmap的最后一个参数)

 

VDSO是切换至内核态的接口,是Linux-gate.so文件的映射,linux-gate.so并不是真实存在的文件
可以通过如下方式查看vdso的内容

dd if=/proc/$pid/mem of=linux-gate.so bs=4096 skip=XXXX count=YYY

/proc/$pid/mem是以地址0x0开始的,而vdso的起始地址为0xffffe000,那么我们需要跳过 0xffffe000/ $bs
所以XXX = Decimal(0xffffe000/$bs)
YYY = 需要dd出的总size(多少倍bs)

3. cat /proc/$pid/smaps  (需要开启内核选项 CONFIG_PROC_PAGE_MONITOR,CONFIG_SLAB)

posted @ 2015-06-04 19:49  xiaokuang  阅读(275)  评论(0编辑  收藏  举报