- 论坛徽章:
- 0
|
源程序如下:
详见 http://blog.chinaunix.net/u/30686/showart_262547.html
#include <stdio.h>
#include <string.h>
int main(void)
{
char *p=(char*)malloc(20);
strcpy(p,"hello,world!\n" ;
printf("%s",p);
return 0;
}
>strace hello
输出如下,我将一行一行的进行分析
execve("/home/e11963/szw/hello/hello", ["/home/e11963/szw/hello/hello"], [/* 27 vars */]) = 0
uname({sys="Linux", node="e11963-lnx", ...}) = 0
brk(0) = 0x9a2f000
//该行主要目的是返回当前堆的虚拟地址。
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
//运行程序时,要分为两步,linker and loader。猜测这行是将linker加载到内存,注意返回值3,在下面做old_mmap时将用到
fstat64(3, {st_mode=S_IFREG|0644, st_size=61838, ...}) = 0
old_mmap(NULL, 61838, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb75e6000
//检查了一下/etc/ld.so.cache的大小,果真为61838,具体参数的意思,大家可以参见mmap的说明。
close(3) = 0
open("/lib/i686/libc.so.6", O_RDONLY) = 3
//开始加载库函数
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\\\1\000"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1560180, ...}) = 0
//1560180为该文件大小。
old_mmap(NULL, 1283620, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x8d8000
//1283620要比该文件小,鉴于内存属性为READ和EXEC,估计是加载code段。
old_mmap(0xa0c000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x134000) = 0xa0c000
old_mmap(0xa0f000, 9764, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xa0f000
//该段内存可写,估计是data段,MAP_ANONYMOUS的含义不清楚。
close(3) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75e5000
//这块内存,不知道什么用处。
munmap(0xb75e6000, 6183 = 0
//这时候linker已经没有用了,从内存中释放掉。
brk(0) = 0x9a2f000
brk(0x9a50000) = 0x9a50000
//对应malloc(20),brk最少申请一个页,glibc再在堆内存上进行管理。
brk(0) = 0x9a50000
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
//makedev(136,1) 136为字符终端设备,开始准备打印
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75f5000
//为字符终端申请内存
write(1, "hello,world!\n", 13hello,world!
) = 13
munmap(0xb75f5000, 4096) = 0
//将为字符终端申请的内存释放掉。
exit_group(0) = ?
Process 4078 detached
int main(void)
{
return 0;
}
结果
execve("/home/e11963/szw/hello/hello", ["/home/e11963/szw/hello/hello"], [/* 27 vars */]) = 0
uname({sys="Linux", node="e11963-lnx", ...}) = 0
brk(0) = 0x8413000
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=61838, ...}) = 0
old_mmap(NULL, 61838, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb75e9000
close(3) = 0
open("/lib/i686/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\\\1\000"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1560180, ...}) = 0
old_mmap(NULL, 1283620, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x645000
old_mmap(0x779000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x134000) = 0x779000
old_mmap(0x77c000, 9764, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x77c000
close(3) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75e8000
munmap(0xb75e9000, 6183 = 0
exit_group(0) = ?
Process 4347 detached
//即使程序什么都不做,也会加载ld和libc函数库。
源程序
#include <stdio.h>
int main(void)
{
char *p=(char*)malloc(10);
malloc(10);
free(p);
return 0;
}
结果
。。。。。。。。
munmap(0xb75ea000, 6183 = 0
brk(0) = 0x8645000
brk(0x8666000) = 0x8666000
brk(0) = 0x8666000
exit_group(0) = ?
Process 4383 detached
虽然malloc了两次,但只做了brk一次,说明glibc在上面做了堆管理。
并且free并没有做系统调用,将内存直接返回给内核。
关于glibc如何做的堆管理还有待研究。 |
|