对于test1.c,我得到:

5
133
1
0

这意味着子进程首先得到SIGTRAP(5),由execl引起。
最后三行指示子进程因SIGSTRAP而终止
来自父母的信号。
// test1.c
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/reg.h>
#include <stdio.h>
#include <pthread.h>

int main() {
  pid_t child;
  int status = 0;
  child = fork();
  if(child == 0) {
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);
    execl("/bin/ls", "ls", NULL);
  } else {
    wait(&status);
    printf("%d\n", status >> 8);
    ptrace(PTRACE_CONT, child, NULL, SIGTRAP);

    wait(&status);
    printf("%d\n", status);
    printf("%d\n", WIFSIGNALED(status));
    printf("%d\n", WIFEXITED(status));
  }
  return 0;
}

对于test2.c,我得到:
19
1029
0
0
1

19是SIGSTOP1029(SIGTRAP | (PTRACE_EVENT_EXEC<<8)),但是
最后三行超出了我的能力范围。孩子为什么会正常退出?来自父母的SIGTRAP信号发生了什么?
// test2.c
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/reg.h>
#include <stdio.h>
#include <pthread.h>
int main() {
  pid_t child;
  int status = 0;
  child = fork();
  if(child == 0) {
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);
    raise(SIGSTOP);
    execl("/bin/ls", "ls", NULL);
  } else {
    wait(&status);
    ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACEEXEC);
    printf("%d\n", status >> 8);
    ptrace(PTRACE_CONT, child, NULL, 0);

    wait(&status);
    printf("%d\n", status >> 8);
    ptrace(PTRACE_CONT, child, NULL, SIGTRAP);

    wait(&status);
    printf("%d\n", status);
    printf("%d\n", WIFSIGNALED(status));
    printf("%d\n", WIFEXITED(status));
  }
  return 0;
}

最佳答案

当跟踪器发送信号时

ptrace(PTRACE_CONT, child, NULL, SIGXXXX);

追踪器没有收到该信号的通知-这是有意义的。否则,你怎么向追踪者发出信号?你总能抓住它。
帕特雷斯康特
重新启动已停止的跟踪进程。如果数据不为零,则为
解释为要传递给
tracee;否则,不发送信号。例如,
追踪器可以控制发送给被追踪器的信号是否
是否送达。
如果你想阻止孩子离开父母,你应该使用
kill(child_pid, SIGTRAP)

所以,我想当你在第一个例子中发送SIGTRAP的时候-你只是简单地发送一个未处理的信号给进程,这可能会杀死他。
另一方面,PTRACE_TRACEME不会导致孩子停止,所以,当SIGTRAP被发送时,它可能已经完成了它的执行。

08-07 20:20