linux 内存管理机制详细解析

物理内存和虚拟内存
我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念。

物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space)。

作为物理内存的扩展,linux会在物理内存不足时,使用交换分区的虚拟内存,更详细的说,就是内核会将暂时不用的内存块信息写到交换空间,这样以来,物理内存得到了释放,这块内存就可以用于其它目的,当需要用到原始的内容时,这些信息会被重新从交换空间读入物理内存。

linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。

要深入了解linux内存运行机制,需要知道下面提到的几个方面:
首先,
Linux系统会不时的进行页面交换操作,以保持尽可能多的空闲物理内存,即使并没有什么事情需要内存,Linux也会交换出暂时不用的内存页面。这可以避免等待交换所需的时间。

其次,linux进行页面交换是有条件的,不是所有页面在不用时都交换到虚拟内存,linux内核根据”最近最经常使用“算法,仅仅将一些不经常使用的页面文件交换到虚拟内存,有时我们会看到这么一个现象:linux物理内存还有很多,但是交换空间也使用了很多。其实,这并不奇怪,例如,一个占用很大内存的进程运行时,需要耗费很多内存资源,此时就会有一些不常用页面文件被交换到虚拟内存中,但后来这个占用很多内存资源的进程结束并释放了很多内存时,刚才被交换出去的页面文件并不会自动的交换进物理内存,除非有这个必要,那么此刻系统物理内存就会空闲很多,同时交换空间也在被使用,就出现了刚才所说的现象了。关于这点,不用担心什么,只要知道是怎么一回事就可以了。

最后,交换空间的页面在使用时会首先被交换到物理内存,如果此时没有足够的物理内存来容纳这些页面,它们又会被马上交换出去,如此以来,虚拟内存中可能没有足够空间来存储这些交换页面,最终会导致linux出现假死机、服务异常等问题,linux虽然可以在一段时间内自行恢复,但是恢复后的系统已经基本不可用了。
因此,合理规划和设计linux内存的使用,是非常重要的.

内存的监控
作为一名linux系统管理员,监控内存的使用状态是非常重要的,通过监控有助于了解内存的使用状态,比如内存占用是否正常,内存是否紧缺等等,监控内存最常使用的命令有free、top等,下面是某个系统free的输出:
[haixigov@WEBServer ~]$ free
             total        used         free      shared   buffers   cached
Mem:         16402432    16360492      41940        0     465404   12714880
-/+ buffers/cache:        3180208   13222224
Swap:        8193108        264      8192844

我们解释下输出结果中每个选项的含义:
首先是第一行:
 total:物理内存的总大小。
 used:已经使用的物理内存多小。
 free:空闲的物理内存值。
 shared:多个进程共享的内存值。
 buffers/cached:磁盘缓存的大小。
第二行Mem:代表物理内存使用情况。
第三行(-/+ buffers/cached):代表磁盘缓存使用状态。
第四行:Swap表示交换空间内存使用状态。
free命令输出的内存状态,可以通过两个角度来查看:一个是从内核的角度来看,一个是从应用层的角度来看的。

从内核的角度来查看内存的状态
就是内核目前可以直接分配到,不需要额外的操作,即为上面free命令输出中第二行Mem项的值,可以看出,此系统物理内存有16G,空闲的内存只有41940K,也就是40M多一点,我们来做一个这样的计算:
16402432-16360492=41940

其实就是总的物理内存减去已经使用的物理内存得到的就是空闲的物理内存大小,注意这里的可用内存值41940并不包含处于buffers和cached状态的内存大小。

如果你认为这个系统空闲内存太小,那你就错了,实际上,内核完全控制着内存的使用情况,linux会在需要内存的时候,或在系统运行逐步推进时,将buffers和cached状态的内存变为free状态的内存,以供系统使用。

从应用层的角度来看系统内存的使用状态
也就是linux上运行的应用程序可以使用的内存大小,即free命令第三行“(-/+ buffers/cached)”的输出,可以看到,此系统已经使用的内存才3180208K,而空闲的内存达到13222224K,继续做这样一个计算:
41940+(465404+12714880)=13222224
通过这个等式可知,应用程序可用的物理内存值是Mem项的free值加上buffers和cached值之和,也就是说,这个free值是包括buffers和cached项大小的,对于应用程序来说,buffers/cached占有的内存是可用的,因为buffers/cached是为了提高文件读取的性能,当应用程序需要用到内存的时候,buffers/cached会很快地被回收,以供应用程序使用。

buffers与cached的异同
在 Linux 操作系统中,当应用程序需要读取文件中的数据时,操作系统先分配一些内存,将数据从磁盘读入到这些内存中,然后再将数据分发给应用程序;当需要往文件中写数据时,操作系统先分配内存接收用户数据,然后再将数据从内存写到磁盘上。然而,如果有大量数据需要从磁盘读取到内存或者由内存写入磁盘时,系统的读写性能就变得非常低下,因为无论是从磁盘读数据,还是写数据到磁盘,都是一个很消耗时间和资源的过程,在这种情况下,linux引入了buffers和cached机制。

buffers与cached都是内存操作,用来保存系统曾经打开过的文件以及文件属性信息,这样当操作系统需要读取某些文件时,会首先在buffers与cached内存区查找,如果找到,直接读出传送给应用程序,如果没有找到需要数据,才从磁盘读取,这就是操作系统的缓存机制,通过缓存,大大提高了操作系统的性能。但buffers与cached缓冲的内容却是不同的。

buffers是用来缓冲块设备做的,它只记录文件系统的元数据(metadata)以及 tracking in-flight pages,而cached是用来给文件做缓冲。更通俗一点说:buffers主要用来存放目录里面有什么内容,文件的属性以及权限等等。而cached直接用来记忆我们打开过的文件和程序。

为了验证我们的结论是否正确,可以通过vi打开一个非常大的文件,看看cached的变化,然后再次vi这个文件,感觉一下两次打开的速度有何异同,是不是第二次打开的速度明显快于第一次呢?
接着执行下面的命令:
 find /* -name  *.conf
看看buffers的值是否变化,然后重复执行find命令,看看两次显示速度有何不同。

Linux操作系统的内存运行原理,很大程度上是根据服务器的需求来设计的,例如系统的缓冲机制会把经常使用到的文件和数据缓存在cached中,linux总是在力求缓存更多的数据和信息,这样再次需要这些数据时可以直接从内存中取,而不需要有一个漫长的磁盘操作,这种设计思路提高了系统的整体性能。

交换空间swap的使用
虽然现在的内存已经变得非常廉价,但是swap仍然有很大的使用价值,合理的规划和使用swap分区,对系统稳定运行至关重要。Linux下可以使用文件系统中的一个常规文件或者一个独立分区作为交换空间使用。同时linux允许使用多个交换分区或者交换文件。

创建swap交换空间
创建交换空间所需的交换文件是一个普通的文件,但是,创建交换文件与创建普通文件不同,必须通过dd命令来完成,同时这个文件必须位于本地硬盘上,不能在网络文件系统(NFS)上创建swap交换文件。例如:
[root@localhost ~]# dd if=/dev/zero of=/data/swapfile bs=1024 count=65536
65536+0 records in
65536+0 records out
这样就创建一个有连续空间的交换文件,大小为60M左右,关于dd命令做简单的讲述:
if=输入文件,或者设备名称。
of=输出文件或者设备名称。
ibs=bytes 表示一次读入bytes 个字节(即一个块大小为 bytes 个字节)。
obs=bytes 表示一次写bytes 个字节(即一个块大小为 bytes 个字节)。
bs=bytes,同时设置读写块的大小,以bytes为单位,此参数可代替 ibs 和 obs。
count=blocks 仅拷贝blocks个块。
skip=blocks 表示从输入文件开头跳过 blocks 个块后再开始复制。
seek=blocks表示从输出文件开头跳过 blocks 个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)
这里的输入设备/dev/zero代表一个输出永远为0的设备文件,使用它作输入可以得到全为空的文件。

激活和使用swap
首先通过mkswap命令指定作为交换空间的设备或者文件:
[root@localhost ~]#mkswap  /data/swapfile
Setting up swapspace version 1, size = 67104 kB
[root@localhost backup]# free
             total       used       free     shared    buffers     cached
Mem:       2066632    1998188      68444          0      26160    1588044
-/+ buffers/cache:     383984    1682648
Swap:      4088500     101036    3987464
从上面输出可知,我们指定了一个67104 kB的交换空间,而此时新建的交换空间还未被使用,下面简单介绍下mkswap命令,mkswap的一般使用格式为:
mkswap [参数] [设备名称或文件][交换区大小]
参数:
-c:建立交换区前,先检查是否有损坏的区块。
-v0:建立旧式交换区,此为预设值。
-v1:建立新式交换区。
交换区大小:指定交换区的大小,单位为1024字节。
设置交换分区后,接着通过swapon命令激活swap:
[root@localhost ~]#/usr/sbin/swapon /data/swapfile
[root@localhost backup]# free
             total       used       free     shared    buffers     cached
Mem:       2066632    1997668      68964          0      27404    1588880
-/+ buffers/cache:     381384    1685248
Swap:      4154028     100976    4053052

通过free命令可以看出,swap大小已经由4088500k变为4154028k,相差的值是60M左右,刚好等于我们增加的一个交换文件大小,这说明新增的交换分区已经可以使用了,但是如果linux重启,那么新增的swap空间将变得不可用,因此需要在/etc/fstab中添加自动加载设置:
 /data/swapfile  none  swap  sw 0 0
如此以来,linux在重启后就可以实现自动加载swap分区了。其实linux在启动过程中会执行“swapon -a”命令,此命令会加载列在/etc/fstab中的所有交换空间。

移除swap
通过swapoff即可移除一个交换空间
[root@localhost ~]#/usr/sbin/swapoff /data/swapfile
其实也可以通过“swapoff -a”移除在/etc/fstab中定义的所有交换空间,这里的“swapoff -a”与上面提到的“swapon -a”对应。执行“swapoff -a”后,free命令输出如下:
[root@localhost backup]# free
             total       used       free     shared    buffers     cached
Mem:       2066632    2048724      17908          0      30352    1642748
-/+ buffers/cache:     375624    1691008

Swap:            0          0          0

(0)

相关推荐

  • 手动释放Linux服务器内存(具体操作步骤)

    在服务器运行过程中,使用free -m查看服务器内存时,经常会发现free值很小,有些同学就会很紧张,总想采取一些措施,使得free值看起来高一点,心里就比较爽一点.其实,个人觉得这完全是图一时之快,没什么实质性用途. 一.大众释放内存方法1. 首先使用free -m查看剩余内存 复制代码 代码如下: linux-8v2i:~ # free -m             total       used       free     shared    buffers     cachedMem

  • linux系统使用python获取内存使用信息脚本分享

    复制代码 代码如下: #!/usr/bin/env Python from __future__ import print_functionfrom collections import OrderedDict def meminfo():    ''' Return the information in /proc/meminfo    as a dictionary '''    meminfo=OrderedDict() with open('/proc/meminfo') as f:  

  • linux中通过文件描述符获取文件绝对路径的方法

    在linux中,有时候我们只知道文件描述符却不知道它的名字及其完整的路径,如果我们想获取其路径该怎么办呢?其实很简单,在linux中每个被打开的文件都会在/proc/self/fd/目录中有记录,其中(/proc/self/fd/文件描述符号)的文件就是文件描述符所对应的文件.说道这里我们先停下了说一个函数: readlink(取得符号连接所指的文件) 相关函数 stat,lstat,symlink 表头文件 #include <unistd.h> 定义函数 int readlink (con

  • 使用python获取CPU和内存信息的思路与实现(linux系统)

    大家都知道,linux里一切皆为文件,在linux/unix的根目录下,有个/proc目录,这个/proc 是一种内核和内核模块用来向进程(process)发送信息的机制(所以叫做"/proc"),这个伪文件系统允许与内核内部数据结构交互,获取有关进程的有用信息,在运行中(on the fly)改变设置(通过改变内核参数).与其他文件系统不同,/proc 存在于内存而不是硬盘中.proc 文件系统提供的信息如下: •进程信息:系统中的任何一个进程,在 proc 的子目录中都有一个同名的

  • linux使用管道命令执行ps获取cpu与内存占用率

    复制代码 代码如下: #include <stdio.h>#include <unistd.h>int main(){    char caStdOutLine[1024]; // ps 命令的标准输出中的一行信息    char* pcTmp = NULL;      // 指向以空格拆分后的字符串 char caSelfPID[10];      // 自身进程的PID字符串    char caPSCmd[24];        // "ps aux | grep

  • Linux内存描述符mm_struct实例详解

    Linux对于内存的管理涉及到非常多的方面,这篇文章首先从对进程虚拟地址空间的管理说起.(所依据的代码是2.6.32.60) 无论是内核线程还是用户进程,对于内核来说,无非都是task_struct这个数据结构的一个实例而已,task_struct被称为进程描述符(process descriptor),因为它记录了这个进程所有的context.其中有一个被称为'内存描述符'(memory descriptor)的数据结构mm_struct,抽象并描述了Linux视角下管理进程地址空间的所有信息

  • 解析Linux系统中JVM内存2GB上限的详解

    我们通常使用的JVM都是32位的(64位的JVM会损失10-20%的性能,通常不建议使用),而32位程序的寻址空间应该是4GB才对,为什么Linux上的JVM内存只能使用2GB呢? 经过和JDK研发组的人员沟通,终于弄清楚了一些相关的原因.这个问题存在于早期的一些Linux版本中,特别是内核2.5以前的版本,2.6以后的版本就基本上没有这个问题了.原来这些Linux版本对进程有个对内存2GB的限制,是一个地址连续的内存块大小的上限,而JVM的堆空间(heap size)需要连续的地址空间,因此,

  • Linux和Windows中tomcat修改内存大小的方法

    其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4.可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置 实例,以下给出1G内存环境下java jvm 的参数设置参考: 复制代码 代码如下: JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M-XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "JAVA_O

  • linux 内存管理机制详细解析

    物理内存和虚拟内存我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念. 物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space). 作为物理内存的扩展,linux会在物理内存不足时,使用交换分区的

  • JavaScript对内存分配及管理机制详细解析

    你可能听说过JAVA..NET.PHP这些语言有垃圾回收的内存管理机制,但是很少会听到JavaScript也有自己的内存管理机制,JavaScript同样有着类似的垃圾回收功能.本文主要讲述了JavaScript的垃圾回收原理和具体的过程. 简介在底层语言中,比如C,有专门的内存管理机制,比如malloc() 和 free().而Javascript是有垃圾回收(garbage collection)机制的,也就是说JS解释器会自动分配和回收内存.这样就有人觉得,我用的是高级语言,就不用关心内存

  • Linux内存管理和寻址详细介绍

    目录 1.概念 内存管理模式 地址类型划分 说明: 2.页式管理 x86架构32位cpu x86架构 64位cpu 3.地址划分 4. 调试 结语 1.概念 内存管理模式 段式:内存分为了多段,每段都是连续的内存,不同的段对应不用的用途.每个段的大小都不是统一的,会导致内存碎片和内存交换效率低的问题. 页式:内存划分为多个内存页进行管理,如在 Linux 系统中,每一页的大小为 4KB.由于分了页后,就不会产生细小的内存碎片.但是仍然也存在内存碎片问题. 段页式:段式和页式结合. 地址类型划分

  • Python超详细讲解内存管理机制

    目录 什么是内存管理机制 一.引用计数机制 二.数据池和缓存 什么是内存管理机制 python中创建的对象的时候,首先会去申请内存地址,然后对对象进行初始化,所有对象都会维护在一 个叫做refchain的双向循环链表中,每个数据都保存如下信息: 1. 链表中数据前后数据的指针 2. 数据的类型 3. 数据值 4. 数据的引用计数 5. 数据的长度(list,dict..) 一.引用计数机制 引用计数增加: 1.1 对象被创建 1.2 对象被别的变量引用(另外起了个名字) 1.3 对象被作为元素,

  • Python 内存管理机制全面分析

    内存管理: 概述 在Python中,内存管理涉及到一个包含所有Python对象和数据结构的私有堆(heap). 这个私有堆的管理由内部的Python内存管理器保证.Python内存管理器有不同的组件来处理各种动态存储管理方面的问题,如共享,分割,预分配或缓存. 在最底层,一个原始内存分配器通过与操作系统的内存管理器交互,确保私有堆有足够的空间来存储所有与Python相关的数据.在原始内存分配器的基础上,几个对象特定的分配器在同一个堆上运行,并根据每种对象类型的特点实现不同的内存管理策略.例如,整

  • 详解php内存管理机制与垃圾回收机制

    一.内存管理机制 先看一段代码: <?php //内存管理机制 var_dump(memory_get_usage());//获取内存方法,加上true返回实际内存,不加则返回表现内存 $a = "laruence"; var_dump(memory_get_usage()); unset($a); var_dump(memory_get_usage()); //输出(在我的个人电脑上, 可能会因为系统,PHP版本,载入的扩展不同而不同): //int 240552 //int

  • FreeRTOS进阶内存管理示例完全解析

    内存管理对应用程序和操作系统来说都非常重要.现在很多的程序漏洞和运行崩溃都和内存分配使用错误有关. FreeRTOS操作系统将内核与内存管理分开实现,操作系统内核仅规定了必要的内存管理函数原型,而不关心这些内存管理函数是如何实现的.这样做大有好处,可以增加系统的灵活性:不同的应用场合可以使用不同的内存分配实现,选择对自己更有利的内存管理策略.比如对于安全型的嵌入式系统,通常不允许动态内存分配,那么可以采用非常简单的内存管理策略,一经申请的内存,甚至不允许被释放.在满足设计要求的前提下,系统越简单

  • python内存管理机制原理详解

    python内存管理机制: 引用计数 垃圾回收 内存池 1. 引用计数 当一个python对象被引用时 其引用计数增加 1 ; 当其不再被变量引用时 引用计数减 1 ; 当对象引用计数等于 0 时, 对象被删除(引用计数是一种非常高效的内存管理机制) 2. 垃圾回收 垃圾回收机制: ① 引用计数 , ②标记清除 , ③分带回收 引用计数 : 引用计数也是一种垃圾收集机制, 而且也是一种最直观, 最简单的垃圾收集技术.当python某个对象的引用计数降为 0 时, 说明没有任何引用指向该对象, 该

  • C语言与C++内存管理超详细分析

    目录 一.内存 1.1 内存四区 1.2 使用代码证实内存四区的底层结构 二.malloc 和 free 2.1 malloc 和 free 的使用 2.2 内存泄漏与安全使用实例与讲解 三.new 和 delete 3.1 new 和 delete 使用 3.2 delete 与 delete[] 的区别 一.内存 在计算机中,每个应用程序之间的内存是相互独立的,通常情况下应用程序 A 并不能访问应用程序 B,当然一些特殊技巧可以访问,但此文并不详细进行说明.例如在计算机中,一个视频播放程序与

  • C语言可变参数与内存管理超详细讲解

    目录 概述 动态分配内存 重新调整内存的大小和释放内存 概述 有时,您可能会碰到这样的情况,您希望函数带有可变数量的参数,而不是预定义数量的参数.C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数.下面的实例演示了这种函数的定义. int func(int, ... ) { . . . } int main() { func(2, 2, 3); func(3, 2, 3, 4); } 请注意,函数func()最后一个参数写成省略号,即三个点号(...)

随机推荐