全部博文(73)
分类: LINUX
2009-04-23 16:47:05
Hello world的系统调用分析
源程序如下:
详见 http://blog.chinaunix.net/u/30686/showart_262547.html
#include
#include
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)
= 0x
//该行主要目的是返回当前堆的虚拟地址。
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(0xa
old_mmap(0xa
//该段内存可写,估计是data段,MAP_ANONYMOUS的含义不清楚。
close(3)
= 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0xb75e5000
//这块内存,不知道什么用处。
munmap(0xb75e6000,
61838)
= 0
//这时候linker已经没有用了,从内存中释放掉。
brk(0)
= 0x
brk(0x
//对应malloc(20),brk最少申请一个页,glibc再在堆内存上进行管理。
brk(0)
= 0x
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) = 0xb
//为字符终端申请内存
write(1, "hello,world!\n", 13hello,world!)
= 13
munmap(0xb
//将为字符终端申请的内存释放掉。
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(0x
close(3)
= 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0xb75e8000
munmap(0xb75e9000,
61838)
= 0
exit_group(0)
= ?
Process 4347 detached
//即使程序什么都不做,也会加载ld和libc函数库。
源程序
#include
int main(void)
{
char *p=(char*)malloc(10);
malloc(10);
free(p);
return 0;
}
结果
。。。。。。。。
munmap(0xb75ea000,
61838)
= 0
brk(0)
= 0x8645000
brk(0x8666000)
= 0x8666000
brk(0)
= 0x8666000
exit_group(0)
= ?
Process 4383 detached
虽然malloc了两次,但只做了brk一次,说明glibc在上面做了堆管理。
并且free并没有做系统调用,将内存直接返回给内核。
关于glibc如何做的堆管理还有待研究。