2.4.0内核中进程的mm_struct释放问题
进程结束时,要通过do_exit退出系统。do_exit()会调用__exit_mm().以下是__exit_mm()的源代码:
static inline void __exit_mm(struct task_struct * tsk)
{
struct mm_struct * mm = tsk->mm;
mm_release();
if (mm) {
atomic_inc(&mm->mm_count);
if (mm != tsk->active_mm) BUG();
/* more a memory barrier than a real lock */
task_lock(tsk);
tsk->mm = NULL;
task_unlock(tsk);
enter_lazy_tlb(mm, current, smp_processor_id());
mmput(mm);
}
}
__exit_mm()先调用atomic_inc(&mm->mm_count)使mm->mm_count加1,使其变成2。最后调用mmput(mm)。其代码如下:
void mmput(struct mm_struct *mm)
{
if (atomic_dec_and_lock(&mm->mm_users, &mmlist_lock)) {
list_del(&mm->mmlist);
spin_unlock(&mmlist_lock);
exit_mmap(mm);
mmdrop(mm);
}
}
可见,在mmput()中,mm->mm_users被减到0。可由于在__exit_mm()调用atomic_inc(&mm->mm_count)使mm->mm_count变成了2,因此在mmdrop(mm)中将mm->mm_count减1后,其值不会达到0,故该进程的mm_struct结构不会被释放。而该进程的父进程,只会调用release_task把它的task_struct结构释放掉。这样,这个进程的mm_struct结构的残骸只能永远留在系统中了,因为该进程的task_struct被释放后,已经没有指针指向它的mm_struct了。
我想我的理解一定有问题,但又不知错在哪,请高人赐教,谢谢!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
mm_release() 只是唤醒父进程,没有其他操作
static inline void __exit_mm(struct task_struct * tsk)
{
struct mm_struct * mm = tsk->mm;
mm_release();
if (mm) {
atomic_inc(&mm->mm_count);
if (mm != tsk->active_mm) BUG();
/* more a memory barrier than a real lock */
task_lock(tsk);
tsk->mm = NULL;
task_unlock(tsk);
enter_lazy_tlb(mm, current, smp_processor_id());
mmput(mm);
}
}
请楼主注意其中的 : tsk->mm = NULL;
同时本进程既然在运行,那么它必须有一个active_mm,眼下的 tsk->active_mm== tsk->mm
现在要tsk->mm = NULL, 所以必须mm->user--,这就是mmput要做的事;
虽然mmput后,mm->user是减减了,但是本进程的active_mm还是在使用着刚释放的这个mm。
而这个mm又不属于本进程,相当于一个借用的mm,而借用其他mm只能mm->count++
从exit_mm返回后,mm确实没有被释放,但是一旦发生schedule(),可能do_exit本身就会显式调用schedule()。
schedule发现将要切换出去的老进程,是一个本身没有mm,借用其他的mm当作active_mm的进程,会对active_mm执行mmdrop的操作。
恩,是有些问题。
不过 __exit_mm 中的 mm_release() 调用,会不会已经将mm->count减为0了呢?