参考博客http://blog.csdn.net/sealyao/article/details/6710772
本人操作系统:ubuntu-14.04
在执行系统调用之前,内核会先检查当前进程是否处于被“跟踪”(traced)的状态。如果是的话,内核暂停当前进程并将控制权交给跟踪进程,使跟踪进程得以察看或者修改被跟踪进程的寄存器。
文中第一个例子,linux/user.h头文件找不到,替换成sys/reg.h,另外还有一个小白问题,代码中调用了printf但没有包含头文件stdio.h
    

 1 #include <sys/ptrace.h>  
 2 #include <sys/types.h>  
 3 #include <sys/wait.h>  
 4 #include <unistd.h>  
 5 #include <sys/reg.h> //modified
 6 #include <stdio.h>  //modified
 7 //#include <linux/user.h>   /* For constants    ORIG_EAX etc */  
 8 int main()  
 9 {  
10     pid_t child;  
11     long orig_eax;  
12     child = fork();  
13     if(child == 0) {  
14         ptrace(PTRACE_TRACEME, 0, NULL, NULL);  
15         execl("/bin/ls", "ls", NULL);  
16     }  
17     else {  
18         wait(NULL);  
19         orig_eax = ptrace(PTRACE_PEEKUSER,   
20                           child, 4 * ORIG_EAX,   
21                           NULL);  
22         printf("The child made a system call %ld ", orig_eax);  
23         ptrace(PTRACE_CONT, child, NULL, NULL);  
24     }  
25     return 0;  
26 }  

 

对于fork()函数,如果运行在父进程中,则返回PID为子进程的进程号,如果在子进程中,则返回的PID为0.
上述代码中,若子进程运行(child==0),调用ptrace开始跟踪子进程(traceme= =),然后执行ls指令,之后的原理文中写的很详细。
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request,pid_t pid,void *addr,void *data);
第一个参数决定了ptrace的行为与其它参数的使用方法。

PTRACE_PEEKUSER
第二个例子主要展示的是参数PTRACE_PEEKUSER的用法。
形式:ptrace(PTRACE_PEEKUSR, pid, addr, data)
描述:从USER区域中读取一个字节,pid表示被跟踪的子进程,USER区域地址由addr给出,data为用户变量地址用于返回读到的数据。USER结构为core文件的前面一部分,它描述了进程中止时的一些状态,如:寄存器值,代码、数据段大小,代码、数据段开始地址等。在Linux(i386)中通过PTRACE_PEEKUSER和PTRACE_POKEUSR可以访问USER结构的数据有寄存器和调试寄存器。

PTRACE_GETREGS
第三个例子与前面的代码是比较相似的,不同的是它使用了PTRACE_GETREGS。使用PRACE_GETREGS作为ptrace的第一个参数来调用,可以只需一次函数调用就取得所有的相关寄存器值。其中的user_regs_struct结构是在<linux/user.h>中定义的(我的系统定义在<sys/user.h>中)。
形式:ptrace(PTRACE_GETREGS, pid, 0, data)
描述:读取寄存器值,pid表示被跟踪的子进程,data为用户变量地址用于返回读到的数据。此功能将读取所有17个基本寄存器的值。

未完待续