LTTng/Perf:用于退出 (sched_process_exit) 和释放 (sched_process_free) 进程的事件之间的区别

问题描述

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

我偶然发现了事件 sched_process_freesched_process_exit。我想知道我目前的理解是否正确:

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

解决方法

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

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

  • set PF_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()删除所有挂起的信号并释放signal_struct描述符并exit_itimers()删除所有定时器
  • 调用 __exit_sighand() 删除信号处理程序
  • 致电__unhash_process()
    • nr_threads--
    • 调用detach_pid()PIDTYPE_PIDPIDTYPE_TGID中删除任务描述符
    • 调用 REMOVE_LINKS 从列表中删除任务
  • 致电sched_exit()安排家长的时间
  • 调用 put_task-struct() 减少计数器,并释放内存和任务描述符
  • 调用delayed_put_task_struct()

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...