1. 环境:
ubuntu 系统 + strace + vim
2.编写挂死程序:(参考博客)
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <string.h> int main(int argc, char** argv) { getpid(); if(argc < 2) { printf("pick one (user|system)\n"); return 1; } if(!strcmp(argv[1], "user")) while(1); else if(!strcmp(argv[1], "system")) sleep(500); return 0; }
3.利用strace查看日志:
root@:~/watson# strace ./a.out user -o user_trace.log execve("./a.out", ["./a.out", "user", "-o", "user_trace.log"], [/* 20 vars */]) = 0 brk(0) = 0x9b49000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7773000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=91359, ...}) = 0 mmap2(NULL, 91359, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb775c000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000\226\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1730024, ...}) = 0 mmap2(NULL, 1743580, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75b2000 mprotect(0xb7755000, 4096, PROT_NONE) = 0 mmap2(0xb7756000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a3) = 0xb7756000 mmap2(0xb7759000, 10972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7759000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75b1000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb75b1900, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0xb7756000, 8192, PROT_READ) = 0 mprotect(0x8049000, 4096, PROT_READ) = 0 mprotect(0xb7796000, 4096, PROT_READ) = 0 munmap(0xb775c000, 91359) = 0 getpid() = 28915
root@:~/watson# strace ./a.out system -o kernel_trace.log execve("./a.out", ["./a.out", "system", "-o", "kernel_trace.log"], [/* 20 vars */]) = 0 brk(0) = 0x8ee6000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7769000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=91359, ...}) = 0 mmap2(NULL, 91359, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7752000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000\226\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1730024, ...}) = 0 mmap2(NULL, 1743580, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75a8000 mprotect(0xb774b000, 4096, PROT_NONE) = 0 mmap2(0xb774c000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a3) = 0xb774c000 mmap2(0xb774f000, 10972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb774f000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75a7000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb75a7900, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0xb774c000, 8192, PROT_READ) = 0 mprotect(0x8049000, 4096, PROT_READ) = 0 mprotect(0xb778c000, 4096, PROT_READ) = 0 munmap(0xb7752000, 91359) = 0 getpid() = 28917 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 nanosleep({500, 0},
tip:
1. 对于user层面测试,出现
getpid() = 28934 ^C--- SIGINT (Interrupt) @ 0 (0) ---
SIGINT的捕捉,中断出现。
对于 getpid() = 28915,则是getid()函数执行的过程,后续无log输出。
陷入while(1)操作。
2. 对于system层面测试,出现
nanosleep({500, 0}, ^C <unfinished ...>
unfinished出现。
nanosleep 是未完整,当修改程序sleep(1)
nanosleep({1, 0}, 0xbfac2df8) = 0 exit_group(0) = ?
最终退出exit_group
是因为在调用sleep时卡死,没法正常运行,是挂死在系统调用。(具体看接口手册)
4. 结论(前提没有exit_group)
1. strace log显示最终的log完整,则卡死在程序逻辑上。
2. strace log显示最终的log不完整,则卡死在系统调用上。
(结论或许有反驳,当调用一个get_id的接口是,该接口自己实现的。)
int get_id() { return 1; }
输出的log不完整,也就挂死在get_id,该也是调用,并非系统调用。
Life is mess, don't let mess mess us.