最近看了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