我找了一些时间来编辑我的答案以使其更清楚。如果还有问题,请告诉我,我们可以讨论并使其更清楚。让我们深入到任务的结尾:
有两个系统调用 :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()
删除所有未决信号并释放信号结构描述符并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 事件点。