Linux free命令详解
2009年07月18日 星期六 13:17
我告诉有朋友我一直用linux.他问我了一下我为什么linux使用的内存这么高.他讲他1G的内在free才232M.讲win xp才用200M的样子.
其实啊.linux的内存是很说究的.
如下显示free是显示的当前内存的使用,-m的意思是M字节来显示内容.我们来一起看看.
$ free -m
total used free shared buffers cached
Mem: 1002 769 232 0 62 421
-/+ buffers/cache: 286 715
Swap: 1153 0 1153
第一部分Mem行:
total 内存总数: 1002M
used 已经使用的内存数: 769M
free 空闲的内存数: 232M
shared 当前已经废弃不用,总是0
buffers Buffer 缓存内存数: 62M
cached Page 缓存内存数:421M
关系:total(1002M) = used(769M) + free(232M)
第二部分(-/+ buffers/cache):
(-buffers/cache) used内存数:286M (指的第一部分Mem行中的used - buffers - cached)
(+buffers/cache) free内存数: 715M (指的第一部分Mem行中的free + buffers + cached)
可见-buffers/cache反映的是被程序实实在在吃掉的内存,而+buffers/cache反映的是可以挪用的内存总数。
第三部分是指交换分区, 我想不讲大家都明白.
我想大家看了上面,还是很晕.第一部分(Mem)与第二部分(-/+ buffers/cache)的结果中有关used和free为什么这么奇怪.
其实我们可以从二个方面来解释.
对操作系统来讲是Mem的参数.buffers/cached 都是属于被使用,所以它认为free只有232.
对应用程序来讲是(-/+ buffers/cach).buffers/cached 是等同可用的,因为buffer/cached是为了提高程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。
所以,以应用来看看,以(-/+ buffers/cache)的free和used为主.所以我们看这个就好了.另外告诉大家一些常识.Linux为了提高磁盘和内存存取效率, Linux做了很多精心的设计, 除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换), 还采取了两种主要Cache方式:Buffer Cache和Page Cache。前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache能有效缩短了 I/O系统调用(比如read,write,getdents)的时间。
记住内存是拿来用的,不是拿来看的.不象windows,无论你的真实物理内存有多少,他都要拿硬盘交换文件来读.这也就是windows为什么常常提示虚拟空间不足的原因.你们想想,多无聊,在内存还有大部分的时候,拿出一部分硬盘空间来充当内存.硬盘怎么会快过内存.所以我们看linux,只要不用swap的交换空间,就不用担心自己的内存太少.如果常常swap用很多,可能你就要考虑加物理内存了.这也是linux看内存是否够用的标准哦.
如果感兴趣可以进一步参考文件/proc/meminfo,free命令就是根据它的信息生成的。free命令的源码可从procps-xxx-.src.rpm获取,xxx为版本号,比如procps-3.2.3-5.3.src.rpm。
在Linux下些C语言程序,最大的问题就是没有一个好的编程IDE,当然想kdevelop等工具都相当的强大,但我还是习惯使用kdevelop工具,由于没有一个习惯的编程IDE,内存检测也就成了在Linux下编写程序的一个大问题。
是不是说没有一种内存检查工具能够在Linux使用呢,也不是,像valgrind工具还是相当不错的。他的下载地址是http://valgrind.org/downloads /current.html#current 下载一个valgrind 3.2.3 (tar.bz2) 工具,按照里面的README提示,安装后就可以使用这个工具来检测内存泄露和内存越界等。这是一个没有界面的内存检测工具,安装后,输入 valgrind ls -l 验证一下该工具是否工作正常(这是README里面的方法,实际上是验证一下对ls -l命令的内存检测),如果你看到一堆的信息说明你的工具可以使用了。
在编译你的程序时,请设置-g参数,编译出后使用如下的命令来判断你的程序存在内存泄露:
valgrind --tools=memcheck --leak-check=full yourProg在输出信息中就会看到你的内存问题了。关于这些参数是什么意思可以参考valgrind --help 的输出信息。
Linux C 编程内存泄露检测工具(一):mtrace
前言
所有使用动态内存分配(dynamic memory allocation)的程序都有机会遇上内存泄露(memory leakage)问题,在Linux里有三种常用工具来检测内存泄露的情況,包括:
1. mtrace
2. dmalloc
3. memwatch
1. mtrace
mtrace是三款工具之中是最简单易用的,mtrace是一个C函數,在<mcheck.h>里声明及定义,函数原型为:
void mtrace(void);
其实mtrace是类似malloc_hook的 malloc handler,只不过mtrace的handler function已由系统为你写好,但既然如此,系统又怎么知道你想将malloc/free的记录写在哪里呢?为此,调用mtrace()前要先设置 MALLOC_TRACE环境变量:
#include <stdlib.h>
....
setenv("MALLOC_TRACE", "output_file_name", 1);
...
「output_file_name」就是储存检测结果的文件的名称。
但是检测结果的格式是一般人无法理解的,而只要有安装mtrace的话,就会有一名为mtrace的Perl script,在shell输入以下指令:
mtrace [binary] output_file_name
就会将output_file_name的內容转化成能被理解的语句,例如「No memory leaks」,「0x12345678 Free 10 was never alloc」诸如此类。
例如以下有一函数:(暂且放下single entry single exit的原则)
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <mcheck.h>
int main() {
char *hello;
setenv("MALLOC_TRACE", "output", 1);
mtrace();
if ((hello = (char *) malloc(sizeof(char))) == NULL) {
perror("Cannot allocate memory.");
return -1;
}
return 0;
}
执行后,再用mtrace 将结果输出:
- 0x08049670 Free 3 was never alloc'd 0x42029acc
- 0x080496f0 Free 4 was never alloc'd 0x420dc9e9
- 0x08049708 Free 5 was never alloc'd 0x420dc9f1
- 0x08049628 Free 6 was never alloc'd 0x42113a22
- 0x08049640 Free 7 was never alloc'd 0x42113a52
- 0x08049658 Free 8 was never alloc'd 0x42113a96
Memory not freed:
-----------------
Address
Size
Caller
0x08049a90
0x1
at 0x80483fe
最后一行标明有一个大小为1 byte的内存尚未释放,大概是指「hello」吧。
若我们把该段内存释放:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <mcheck.h>
int main() {
char *hello;
setenv("MALLOC_TRACE", "output", 1);
mtrace();
if ((hello = (char *) malloc(sizeof(char))) == NULL) {
perror("Cannot allocate memory.");
return -1;
}
free(hello);
return 0;
}
结果如下:
- 0x080496b0 Free 4 was never alloc'd 0x42029acc
- 0x08049730 Free 5 was never alloc'd 0x420dc9e9
- 0x08049748 Free 6 was never alloc'd 0x420dc9f1
- 0x08049668 Free 7 was never alloc'd 0x42113a22
- 0x08049680 Free 8 was never alloc'd 0x42113a52
- 0x08049698 Free 9 was never alloc'd 0x42113a96
No memory leaks.
mtrace的原理是记录每一对malloc-free的执行,若每一个malloc都有相应的free,则代表没有内存泄露,对于任何非malloc/free情況下所发生的内存泄露问题,mtrace并不能找出来。
Memwatch简介
在三种检测工具当中,设置最简单的算是memwatch,和dmalloc一样,它能检测未释放的内存、同一段内存被释放多次、位址存取错误及不当使用未分配之内存区域。请往http://www.linkdata.se/sourcecode.html下载最新版本的Memwatch。
安装及使用memwatch
很幸运地,memwatch根本是不需要安装的,因为它只是一组C程序代码,只要在你程序中加入memwatch.h,编译时加上-DMEMWATCH -DMW_STDIO及memwatch.c就能使用memwatch,例如:
gcc -DMEMWATCH -DMW_STDIO test.c memwatch.c -o test
memwatch输出結果
memwatch 的输出文件名称为memwatch.log,而且在程序执行期间,所有错误提示都会显示在stdout上,如果memwatch未能写入以上文件,它会尝试写入memwatchNN.log,而NN介于01至99之间,若它仍未能写入memwatchNN.log,则会放弃写入文件。
我们引用第一篇(mtrace)中所使用过的有问题的代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <memwatch.h>
int main() {
char *hello;
setenv("MALLOC_TRACE", "output", 1);
mtrace();
if ((hello = (char *) malloc(sizeof(char))) == NULL) {
perror("Cannot allocate memory.");
return -1;
}
return 0;
}
然后在shell中输入以下编译指令:
gcc -DMEMWATCH -DMW_STDIO test.c memwatch.c -o test
memwatch.log的內容如下:
============= MEMWATCH 2.71 Copyright (C) 1992-1999 Johan Lindh =============
Started at Sat Jun 26 22:48:47 2004
Modes: __STDC__ 32-bit mwDWORD==(unsigned long)
mwROUNDALLOC==4 sizeof(mwData)==32 mwDataSize==32
Stopped at Sat Jun 26 22:48:47 2004
unfreed: <1> test.c(9), 1 bytes at 0x805108c
{FE .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .}
Memory usage statistics (global):
N)umber of allocations made: 1
L)argest memory usage
: 1
T)otal of all alloc() calls: 1
U)nfreed bytes totals
: 1
文件指出,在test.c被执行到第9行时所分配的内存仍未被释放,该段内存的大小为1 byte。
Memwatch使用注意
Memwatch 的优点是无需特別配置,不需安装便能使用,但缺点是它会拖慢程序的运行速度,尤其是释放内存时它会作大量检查。但它比mtrace和dmalloc多了一项功能,就是能模拟系统内存不足的情況,使用者只需用mwLimit(long num_of_byte)函数来限制程式的heap memory大小(以byte单位)。