ptrace系统调用的原型为:
long ptrace (enum __ptrace_request request,pid_t pid,void *addr,void *data);
其中,request表明了我们向ptrace请求的服务。在list1的示例中,我们使用的是PTRACE_TRACEME表明了子进程主动要求被跟踪的意愿。而且对于PTRACE_TRACEME,其他的参数均被忽略。
一旦子进程声明自己已经准备好被跟踪,任何发送给该进程的信号(SIGKILL除外)。都会导致这个进程被暂停(stopped)。因此向子进程发送的SIGINT(CTRL+C)就导致了该子进程暂停。
从list1这个简单的demo中我们可以总结出ptrace的大概流程:
1、父进程fork了子进程,子进程执行exec系统调用和父进程分离。
题外话:
我们在这里简单说一下fork和exec吧!
从这个图中我们可以看出:fork就是子进程复制了父进程几乎所有的信息,然后执行自己的那个分支语句,而exec就是执行了另外一个程序段,只是保留了进程号(细节我们在这里就不讨论了)。
2、父进程向子进程发送一个信号,等待子进程的响应
3、当子进程暂停(stopped),父进程就可以使用ptrace系统调用所提供的不同的参数实现各种不同的功能了。
4、当父进程干完了自己想干的事情,就重启子进程,让其继续执行。(或者通过ptrace特殊的参数使得ptrace在进入/退出下一次系统调用(PTRACE_SYSCALL),执行完一条指令之后(PTRACE_SINGLESTEP)暂停)。