在前面,我们接触到了很多函数能够实现系统相关的功能,比如解析命令行参数、控制进程以及映射内存等等。实际上,这些函数能够分为两大类:
-
库函数——这些函数就像普通函数一样,参数放置在寄存器或者栈里,运行时就从动态库里加载。
-
系统调用——这类函数的参数被打包传递到内核,由内核执行作业。例如低级I/O操作,
open
或者read
。
Linux提供了200多种不同的系统调用。他们大多声明在/usr/include/asm/unistd.h
文件里。
1 strace
命令
strace
命令能够跟踪另一个程序的执行情况,给出其执行的系统调用和接收到的信号中断。
如果要追踪hostname
命令,就可以执行:
$ strace hostname
execve("/bin/hostname", ["hostname"], [/* 10 vars */]) = 0
brk(0) = 0x255f000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe7b3f38000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=16300, ...}) = 0
mmap(NULL, 16300, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe7b3f34000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF211 3 >