在linux的内存分配机制中,优先使用物理内存,当物理内存还有空闲时(还够用),不会释放其占用内存,就算占用内存的程序已经被关闭了,该程序所占用的内存用来做缓存使用,对于开启过的程序、或是读取刚存取过得数据会比较快。

一. 我们先来查看一个内存使用的例子:
[oracle@db1 ~]$ free -m
                total       used       free     shared    buffers     cached
Mem:        72433     67075      5357      0        558       62221
-/+ buffers/cache:     4295      68138
Swap:        72096      91       72004
上述结果显示了67075M的used,但是(-/+ buffers/cache)减去buffers和cache的结果可以看到,所以当前进程实际占用内存是4296M。
可以这么理解:在linux的内存分配机制中,优先使用物理内存,当物理内存还有空闲时(还够用),不会释放其占用内存,就算占用内存的程序已经被关闭了,该程序所占用的内存用来做缓存使用,对于开启过的程序、或是读取刚存取过得数据会比较快。
如上面的例子:使用了72433M的内存,67075M被占用,但是buuffer和cached部分作为缓存,可以使用命中率的方式提高使用效率,而且这部分缓存是根据指令随时可以释放的,我们可以认为这部分内存没有实际被使用,也可以认为它是空闲的。
因此查看目前进程正在实际被使用的内存,是used-(buffers+cache),也可以认为如果swap没有大量使用,mem还是够用的,只有mem被当前进程实际占用完(没有了buffers和cache),才会使用到swap的。
二. Swap配置对性能的影响
分配太多的Swap空间会浪费磁盘空间,而Swap空间太少,则系统会发生错误。 如果系统的物理内存用光了,系统就会跑得很慢,但仍能运行;如果Swap空间用光了,那么系统就会发生错误。例如,Web服务器能根据不同的请求数量衍生出多个服务进程(或线程),如果Swap空间用完,则服务进程无法启动,通常会出现“application is out of memory”的错误,严重时会造成服务进程的死锁。因此Swap空间的分配是很重要的。

通常情况下,Swap空间应大于或等于物理内存的大小,最小不应小于64M,通常Swap空间的大小应是物理内存的2-2.5倍。但根据不同的应用,应有不同的配置:如果是小的桌面系统,则只需要较小的Swap空间,而大的服务器系统则视情况不同需要不同大小的Swap空间。特别是数据库服务器和Web服务器,随着访问量的增加,对Swap空间的要求也会增加,一般来说对于4G 以下的物理内存,配置2倍的swap,4G 以上配置1倍。
另外,Swap分区的数量对性能也有很大的影响。因为Swap交换的操作是磁盘IO的操作,如果有多个Swap交换区,Swap空间的分配会以轮流的方式操作于所有的Swap,这样会大大均衡IO的负载,加快Swap交换的速度。如果只有一个交换区,所有的交换操作会使交换区变得很忙,使系统大多数时间处于等待状态,效率很低。用性能监视工具就会发现,此时的CPU并不很忙,而系统却慢。这说明,瓶颈在IO上,依靠提高CPU的速度是解决不了问题的。
三.  Linux 内存机制
Linux支持虚拟内存(Virtual Mmemory),虚拟内存是指使用磁盘当作RAM的扩展,这样可用的内存的大小就相应地增大了。内核会将暂时不用的内存块的内容写到硬盘上,这样一来,这块内存就可用于其它目的。当需要用到原始的内容时,它们被重新读入内存。这些操作对用户来说是完全透明的;Linux下运行的程序只是看到有大量的内存可供使用而并没有注意到时不时它们的一部分是驻留在硬盘上的。当然,读写硬盘要比直接使用真实内存慢得多(要慢数千倍),所以程序就不会象一直在内存中运行的那样快。用作虚拟内存的硬盘部分被称为交换空间(Swap Space)。
一般,在交换空间中的页面首先被换入内存;如果此时没有足够的物理内存来容纳它们又将被交换出来(到其他的交换空间中)。如果没有足够的虚拟内存来容纳所有这些页面,Linux就会波动而不正常;但经过一段较长的时间Linux会恢复,但此时系统已不可用了。
有时,尽管有许多的空闲内存,仍然会有许多的交换空间正被使用。这种情况是有可能发生的,例如如果在某一时刻有进行交换的必要,但后来一个占用很多物理内存的大进程结束并释放内存时。被交换出的数据并不会自动地交换进内存,除非有这个需要时。此时物理内存会在一段时间内保持空闲状态。对此并没有什么可担心的,但是知道了是怎么一回事,也就无所谓了。
许多操作系统使用了虚拟内存的方法。因为它们仅在运行时才需要交换空间,以解决不会在同一时间使用交换空间,因此,除了当前正在运行的操作系统的交换空间,其它的就是一种浪费。所以让它们共享一个交换空间将会更有效率。
注意:如果会有几个人同时使用这个系统,他们都将消耗内存。然而,如果两个人同时运行一个程序,内存消耗的总量并不是翻倍,因为代码页以及共享的库只存在一份。

Linux系统常常动不动就使用交换空间,以保持尽可能多的空闲物理内存。即使并没有什么事情需要内存,Linux也会交换出暂时不用的内存页面。这可以避免等待交换所需的时间:当磁盘闲着,就可以提前做好交换。可以将交换空间分散在几个硬盘之上。针对相关磁盘的速度以及对磁盘的访问模式,这样做可以提高性能。

与访问物理内存相比,磁盘的读写是很慢的。另外,在相应较短的时间内多次读磁盘同样的部分也是常有的事。例如,某人也许首先阅读了一段E-mail消息,然后为了答复又将这段消息读入编辑器中,然后又在将这个消息拷贝到文件夹中时,使得邮件程序又一次读入它。或者考虑一下在一个有着许多用户的系统中 ls命令会被使用多少次。通过将信息从磁盘上仅读入一次并将其存于内存中,除了第一次读以外,可以加快所有其它读的速度。这叫作磁盘缓冲(Disk Buffering),被用作此目的的内存称为高速缓冲(Buffer Cache)。但是,由于内存是一种有限而又不充足的资源,高速缓冲不可能做的很大(它不可能包容要用到的所有数据)。当缓冲充满了数据时,其中最长时间不用的数据将被舍弃以腾出内存空间用于新的数据。

对写磁盘操作来说磁盘缓冲技术同样有效。一方面,被写入磁盘的数据常常会很快地又被读出(例如,原代码文件被保存到一个文件中,又被编译器读入),所以将要被写的数据放入缓冲中是个好主意。另一方面,通过将数据放入缓冲中,而不是将其立刻写入磁盘,程序可以加快运行的速度。以后,写的操作可以在后台完成,而不会拖延程序的执行。
大多数操作系统都有高速缓冲(尽管可能称呼不同),但是并不是都遵守上面的原理。有些是直接写(Write-Through):数据将被立刻写入磁盘(当然,数据也被放入缓存中)。如果写操作是在以后做的,那么该缓存被称为后台写(Write-Back)。后台写比直接写更有效,但也容易出错:如果机器崩溃,或者突然掉电,缓冲中改变过的数据就被丢失了。如果仍未被写入的数据含有重要的薄记信息,这甚至可能意味着文件系统(如果有的话)已不完整。
针对以上的原因,出现了很多的日志文件系统,数据在缓冲区修改后,同时会被文件系统记录修改信息,这样即使此时系统掉电,系统重启后会首先从日志记录中恢复数据,保证数据不丢失。当然这些问题不再本文的叙述范围。
由于上述原因,在使用适当的关闭过程之前,绝对不要关掉电源,Sync命令倾空(Flushes)缓冲,也即,强迫所有未被写的数据写入磁盘,可用以确定所有的写操作都已完成。在传统的UNIX系统中,有一个叫做update的程序运行于后台,每隔30秒做一次sync操作,因此通常无需手工使用sync命令了。Linux另外有一个后台程序,Bdflush,这个程序执行更频繁的但不是全面的同步操作,以避免有时sync的大量磁盘I/O操作所带来的磁盘的突然冻结。
在Linux中,Bdflush是由update启动的。通常没有理由来担心此事,但如果由于某些原因bdflush进程死掉了,内核会对此作出警告,此时你就要手工地启动它了(/sbin/update)。
缓存(Cache)实际并不是缓冲文件的,而是缓冲块的,块是磁盘I/O操作的最小单元(在Linux中,它们通常是1KB)。这样,目录、超级块、其它文件系统的薄记数据以及非文件系统的磁盘数据都可以被缓冲了。缓冲的效力主要是由它的大小决定的。缓冲太小的话等于没用。它只能容纳一点数据,因此在被重用时,所有缓冲的数据都将被倾空。实际的大小依赖于数据读写的频次、相同数据被访问的频率。只有用实验的方法才能知道。
如果缓存有固定的大小,那么缓存太大了也不好,因为这会使得空闲的内存太小而导致进行交换操作(这同样是慢的)。为了最有效地使用实际内存,Linux自动地使用所有空闲的内存作为高速缓冲,当程序需要更多的内存时,它也会自动地减小缓冲的大小。 
这就是一般情况下Linux内存的一般机制,真正的Linux内存的运行机制远远比这个复杂。

http://bbs.chinaunix.net/thread-3609448-1-1.html

linux内存分配的更多相关文章

  1. 深入理解Linux内存分配

    深入理解Linux内存分配 为了写一个用户层程序,你也许会声明一个全局变量,这个全局变量可能是一个int类型也可能是一个数组,而声明之后你有可能会先初始化它,也有可能放在之后用到它的时候再初始化.除此 ...

  2. Linux内存分配----SLAB

    动态内存管理 内存管理的目标是提供一种方法,为实现各种目的而在各个用户之间实现内存共享.内存管理方法应该实现以下两个功能: 最小化管理内存所需的时间 最大化用于一般应用的可用内存(最小化管理开销) 内 ...

  3. 从malloc中窥探Linux内存分配策略

        malloc函数是C/C++中常用内存分配库函数,本篇文章将以Linux平台上的malloc为剖析对象,深入了解分配一块内存的旅程. malloc入门      使用malloc,需要包含头文 ...

  4. linux内存分配机制

    这几天在观察apache使用内存情况,所以特意了解了下linux的内存机制,发现一篇写得还不错.转来看看. 一般来说在ps aux中看到的rss就是进程所占用的物理内存.但是如果将所有程序的rss加起 ...

  5. Linux内存分配小结--malloc、brk、mmap【转】

    转自:https://blog.csdn.net/gfgdsg/article/details/42709943 http://blog.163.com/xychenbaihu@yeah/blog/s ...

  6. Linux内存分配机制之伙伴系统和SLAB

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6539590.html  内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下,避免碎片的产生.这就要求 ...

  7. linux内存分配方法总结【转】

    转自:http://www.bkjia.com/Linuxjc/443717.html 内存映射结构: 1.32位地址线寻址4G的内存空间,其中0-3G为用户程序所独有,3G-4G为内核占有. 2.s ...

  8. linux内存分配与回收

    前言 之前在实习时,听了 OOM 的分享之后,就对 Linux 内核内存管理充满兴趣,但是这块知识非常庞大,没有一定积累,不敢写下,担心误人子弟,所以经过一个一段时间的积累,对内核内存有一定了解之后, ...

  9. Linux 内存分配失败(关于overcommit_memory)

    1.问题现象和分析:测试时发现当系统中空闲内存还有很多时,就报内存分配失败了,所有进程都报内存分配失败:sshd@localhost:/var/log>free             tota ...

随机推荐

  1. 添加本地jar到Maven库

    转自:http://dk05408.iteye.com/blog/2170986 上传: mvn install:install-file -Dfile=D:/workspace/p2p_server ...

  2. java 设置允许ajax XMLHttpRequest 请求跨域访问

    怎样才能算跨域?协议,域名,端口都必须相同,才算在同一个域. 方案1: 使用XMLHttpRequest...  异步请求不能跨域访问,除非要访问的网页响应头信息设置为允许跨域访问. 将网页设置为允许 ...

  3. hdu 5585 Numbers

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5585 思路:对于2和5只须看最后一位数,对于三看所有位的数字之和就行 #include<stdi ...

  4. Python科学计算发行版—Anaconda

    Python是一种强大的编程语言,其提供了很多用于科学计算的模块,常见的包括numpy.scipy和matplotlib.要利用Python进行科学计算,就需要一一安装所需的模块,而这些模块可能又依赖 ...

  5. Oracle性能优化之SQL语句

    1.SQL语句执行过程 1.1 SQL语句的执行步骤 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义. 2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限. ...

  6. Oracle 备份与恢复介绍

    一.Oracle备份方式分类:Oracle有两类备份方式:(1)物理备份:是将实际组成数据库的操作系统文件从一处拷贝到另一处的备份过程,通常是从磁盘到磁带.物理备份又分为冷备份.热备份:   (2)逻 ...

  7. js 随机星星 document.createElement(); setAttribute()

    js 随机星星 document.createElement(); setAttribute() <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. ...

  8. C#DataGridView合计处理

    网上查了一些关于合计的代码 ,但发现大都都不尽人意,就自己再根据资料改了一下. #region 合计 //调用方法示例 //HeJi heji = null; //heji = new HeJi(la ...

  9. android 入门-android Studio git 克隆

    最后是完成 以上是如何从android studio Git 克隆Github的项目

  10. Linux系统启动流程及安装命令行版本

    Debian安装 之前也安装过很多次linux不同版本的系统,但安装后都是直接带有桌面开发环境的版本,直接可以使用,正好最近项目不是很忙,想一直了解下Linux的整个启动流程,以及如何从命令行模式系统 ...