2

目前,我正在讨论使用 LTTng 和 Perf 进行内核跟踪的主题。我对追踪一个进程所处的不同状态特别感兴趣。

我偶然发现了这个事件sched_process_free,然后sched_process_exit。我想知道我目前的理解是否正确:

如果退出进程,则将其sched_process_exit写入跟踪。但是,进程描述符可能仍在内存中,这会导致僵尸进程。当连接到进程的整个内存被释放时,sched_process_free被调用。这意味着,如果我真的想确保进程完全“终止”并从内存中删除,我必须听sched_process_free而不是sched_process_exit跟踪。这个对吗?

4

1 回答 1

1

我找了一些时间来编辑我的答案以使其更清楚。如果还有问题,请告诉我,我们可以讨论并使其更清楚。让我们深入到任务的结尾:

有两个系统调用 :exit_group()exit(),它们都将转到do_exit(),它将执行以下操作。

  • setPF_EXTING表示任务正在删除
  • 从定时器中删除任务描述符del_timer_sync()
  • 调用exit_mm(), exit_sem(), __exit_fs()和其他人释放该任务的结构
  • 调用perf_event_exit_task ( tsk );
  • 减少参考计数
  • 设置exit_code_exit()/exit_group()或错误
  • 称呼exit_notify()
    • 更新与父母和孩子的关系
    • 检查exit_signal,发送SIGCHLD
    • 如果未跟踪任务或返回值为 -1,则将 exit_state 设置为EXIT_DEAD,调用release_task()以回收其他内存并减少引用计数。
    • 如果跟踪任务,则将 exit_state 设置为EXIT_ZOMBIE
    • 将任务标志设置为PF_DEAD
  • 称呼schedule()

我们需要僵尸状态,因为父级可能需要使用那些文件描述符,所以我们不能在第一时间删除所有的东西。父任务将需要使用类似的东西wait()来检查孩子是否死了。之后wait(),是时候让僵尸完全释放了release_task()

  • 减少所有者的任务编号
  • ptrace_children如果任务被跟踪,从列表中删除
  • 调用__exit_signal()删除所有未决信号并释放信号结构描述符并exit_itimers()删除所有计时器
  • 调用__exit_sighand()删除信号处理程序
  • 称呼__unhash_process()
    • nr_threads--
    • 调用detach_pid()PIDTYPE_PID和删除任务描述符PIDTYPE_TGID
    • 调用REMOVE_LINKS从列表中删除任务
  • 打电话sched_exit()安排父母的时间片
  • 调用put_task-struct()以减少计数器,并释放内存和任务描述符
  • 调用delay_put_task_struct()

所以,我们知道sched_process_exit状态会在 do_exit() 中进行,但是我们无法确定进程是否被释放(可以调用 release_task() 或不调用,这将触发sched_process_free)。这就是为什么我们需要两个 perf 事件点。

于 2021-01-08T08:43:22.417 回答