转自:http://www.xuebuyuan.com/2223733.html
打算优化系统的内存分配,接管
glibc方案
1
使用环境变量
LD_PRELOAD
环境变量
LD_PRELOAD
指定程序运行时优先加载的动态连接库,这个动态链接库中的符号优先级是最高的。标准
C
的各种函数都是存放在
libc.so.6
的文件中,在程序运行时自动链接。使用
LD_PRELOAD
后,自己编写的
malloc
的加载顺序高于
glibc
中的
malloc
,这样就实现了替换。用法:
[littlefang]$
LD_PRELOAD=" ./mymalloc.so"
这是最实用的替换方法,动态链接库加载过程中提供了初始化函数,可以轻易的获得系统
malloc
的句柄,再将它做进一步的管理,
Hoard
(参见
深入
Linux
的内存管理,关于
PTMalloc3
、
Hoard
和
TCMalloc
)的就是这样实现的。
方案
2
malloc
调试变量
__malloc_hook
是一组
glibc
提供的
malloc
调试变量中的一个,这组变量包括:
只要你在程序中写上
”__malloc_hook
= my_malloc_hook;”
,之后的
malloc
调用都会使用
my_malloc_hook
函数,方便易行。但是这组调试变量不是线程安全的,当你想用系统
malloc
的时候不得不把他们改回来,多线程调用就得上锁了。因此方案
2
不很适用于系统内存优化,勉强用来简单管理线程内存使用。
详细用法请猛击这里
方案
3
编译自己的
libmalloc.a
关于重载
glibc
的
malloc
库,
ChinaUnix
上有这样的讨论
:
如果我用
cc -o myprog
myprog.c -lmylib
,
而不想修改缺省的
ld
的命令行参数或者
linker
脚本,不知可不可以?
这个方法确实比较理想,只需要
make
一次就
OK
了,不用更改环境变量,省得担心后台运行的问题。后面有人回复让楼主试试,不知道楼主试了没有,我试了一下。
若要把系统内存管理起来,首先还是要向操作系统申请内存,这个问题对于
LD_PRELOAD
方案很简单,链接库加载时就可以把
glibc
中的
malloc
加载进来,以后直接调用就可以了,如:
real_malloc =
dlsym(RTLD_NEXT, "malloc");
但是你如果使用自己编译的
malloc
库,在你调用
dlsym
这个函数时,
dlsym
会调用
dlerror
,
dlerror
会调用
calloc
,
calloc
要调用
malloc
,而你的
malloc
正在初始化等待
dlsym
返回中,于是死循环了。有人说,在调用没有初始化完毕的
malloc
时,返回
NULL
,我试了
dlsym
不认账,加载可耻的失败了。在满世界的寻找
dlsym
的替代品未果后,我把目光瞄住了
tcmalloc
(参见
深入
Linux
的内存管理,关于
PTMalloc3
、
Hoard
和
TCMalloc
)。
Tcmalloc
使用时需要在链接时加上
-ltcmalloc
即可,它代码里也没使用
dlsym
,大略了看了下它的代码,它使用
mmap
从系统获取的内存。
void *mmap(void
*addr, size_t len, int prot, int flags, int fildes, off_t off);
这种方法从页面级就要对系统内存进行管理,
Glibc
中的
malloc
就是使用
mmap
和
brk
两个函数从程序堆中获得内存的。无疑,这比起用
malloc
分配的内存复杂了很多。
方案
4
链接过程控制
ld
中有一个选项
–wrap
,当查找某个符号时,它优先先解析
__wrap_symbol,
解析不到才去解析
symbol
。例如:
当其它文件与你实现
__wrap_malloc
函数的文件链接时使用
--wrap
malloc
,则所有到
malloc
的调用都是会链接到
__wrap_malloc
上。只有调用
__reall_malloc
时才会调用真正的
malloc
。
编译
[littlefang]$
gcc wrap.c -o wrap -Wl,-wrap,malloc
运行
[littlefang]$
./wrapMy MALLOC
called: 12
Gcc
或
g++
编译使用
–Wl
选项,以指定链接器参数,比如同时替换
malloc,free
,
realloc
就要用
gcc wrap.c -o wrap -Wl,-wrap,malloc
-Wl,-wrap,free
-Wl,-wrap,realloc
。
特别需要注意的是,如果你的
__wrap_malloc是用
C++
实现的,千万不要忘记加上
extern
“C”
做修饰,不然会出现"undefine reference to __wrap_malloc"。