最近看了emytymonkey大佬的项目,感觉有很多有意思的项目,都基于了同一个Linux系统调用---ptrace,让我来详细看看这个神秘而强大的ptrace是什么.
本篇文章基于大佬的详细解析
https://recursiveg.me/2014/04/programming-with-ptrace-part1/
fork(), vfork() 与 clone()
我们知道,在linux中每个进程都有唯一的编号:pid,进程都是由父进程产生的,不会存在没有父进程的进程.所以进程是如何产生的呢?
一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
原文链接:https://blog.csdn.net/jason314/article/details/5640969
?为什么只 print 了一次?应该是这个在线运行的问题
正常返回是这样的
print被调用了两次,说明在fork后整个程序被执行了两次,一次父进程,一次子进程,那么作为当前执行进程的进程本身,怎样自己确认是子进程还是主进程呢?
看函数返回值,当在子进程时,fork函数返回值为0,父进程中子进程的返回值为子进程的pid
可以观察一下 vfork 换成 fork 输出结果
简单来说,vfork()保存父进程fork钱变量,fork()不保存
还是从大佬的代码开始学起
#include <stdio.h>#include <unistd.h>#include <sys/ptrace.h>#include <sys/wait.h>#include <sys/resource.h>#include <sys/reg.h>int main(){puts("Parent started");pid_t pid;pid=fork();if (pid<0){puts("fork() failed");return(-1);}if (pid==0){ptrace(PTRACE_TRACEME,0,0,0);puts("Child sleeping...");sleep(1);puts("Child exec...");execlp("./target","target",NULL);}else{printf("Child PiD == %d\n",pid);int sta=0;struct rusage ru;wait4(pid,&sta,0,&ru);long rax_rt=ptrace(PTRACE_PEEKUSER,pid,8*RAX,0);printf("Child execve() returned with %ld\n",rax_rt);ptrace(PTRACE_SYSCALL,pid,0,0);int intocall=1;while(1){wait4(pid,&sta,0,&ru);if (WIFEXITED(sta)){puts("Child Exited");break;}long _ORIG_RAX=ptrace(PTRACE_PEEKUSER,pid,8*ORIG_RAX,0);long _RAX=ptrace(PTRACE_PEEKUSER,pid,8*RAX,0);if (intocall){p