Linux进程退出与销毁PID结构体的关系

Linux中是有PID分配回绕的。为了研究这个问题,需要搞清楚,PID号什么时候会被释放(即可以再次被分配给别的进程使用这个号码)。
在这里插入图片描述

PID号释放在整个free_pid按照pid->level的循环,把ns->idr释放掉,但是pid结构体并不一定被释放,只是put_pid。

put_pid的引用计数减少为0时,调用kmem_cache_free真正的把pid这个结构体释放掉。

😕task_struct在这个过程中起到了什么作用?调用exit的时候,是否有减为0 呢?

在进程执行do_exit以后,进程被标记位僵尸进程状态,这个时候做了很多操作,但是并不是do_exit过程中就会把task_struct回收掉,

😮那是在什么时候回收的呢?

do_exit中有一个函数是exit_notify,他会“让子进程忘记自己”。

如果正在退出的进程不是线程组的领导进程,会直接被回收,调用release_task,进程状态被标记为EXIT_DEAD

如果正在退出的进程时线程组的领导进程,其是否被直接回收取决于do_notify_parent的返回值,即父进程对这个子进程即将退出的处理策略,如果父进程不感兴趣,将返回true,立刻被回收,调用release_task,进程状态被标记为EXIT_DEAD;如果父进程感兴趣,将返回false,不会立刻回收,进程状态被标记为EXIT_ZOMBIE

👿但是,重点是,不管以上哪种方式,task_struct都并不是在do_exit中回收的,而是在,do_exit的最后,执行__schedule里,进程切换完毕后,被调度执行的进程在schedule_tail->finish_task_switch中完成的。在设置了进程状态为TASK_DEAD后, 进程进入僵死状态, 进程已经无法被再次调度, 因为对应用程序或者用户空间来说此进程已经死了, 但是尽管进程已经不能再被调度,但系统还是保留了它的进程描述符,这样做是为了让系统有办法在进程终止后仍能获得它的信息。

finish_task_switch里面会调用put_task_stackput_task_struct_rcu_user,前者会释放进程的栈,后者会给rcu设置一个回调函数delayed_put_task_struct,当task->rcu_users减少为0时执行,delayed_put_task_struct里才会走到最终的put_task_struct。而put_task_struct的关键在于用他的引用计数来控制释放。
只要进程被标记为EXIT_DEAD状态,就会调用release_task,就会释放PID号,但不一定会释放pid结构体。

PID号在进程退出时被杀死,PID号被回收;但是此时新创建的进程不会立刻就分配这个号,而是在这个命名空间里,从可用的pid号已经达到了最大极限以后,才会从头回绕,回绕后也不一定是立刻就把这个号分配重用。使用了延迟重用算法,防止刚释放的号码被立即使用。

结论:
经过分析,Linux中PID号和pid结构体是两个分开独立的东西。PID号是进程退出的时候,就可能被回收掉的,当然这里有一些条件,首先这个进程要满足EXIT_DEAD状态,其次要满足!pid_has_task,满足这两点,PID号就会被回收。回收以后,也并不会立即分配,而是当PID号已经被用完达到最大以后,再从起始位置回绕,call this延迟重用算法。起始位置应该是300,有个宏定义是保留PID号,留给那些启动进程什么的。这是PID号的事,然后对pid结构体做了什么呢?仅仅对pid结构体的引用计数减一。减一意味着并不是立即释放,而是等它减到0的时候才去释放,这样即使PID号被释放了,但你持有的pid结构体指针,你依旧可以找到你想要的数据和task_struct数据,而并不是因为pid号换了,就拿到新的进程里的东西了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值