在linux中可以实现进程挂靠,通过use_mm函数可以将当前进程(或线程,linux不区分)的地址空间设置为特定的mm_struct,先不管函 数的形态是否一致,它和windows的KeAttachProcess的作用是一样的,它同样要切换硬件上下文,但是别的方面设置却非常简单。这一切有 一个终极原因和一个辅助原因两个原因:1.linux的全局页目录不和进程挂钩,而是和地址空间挂钩(pgd在mm_struct里而没有在 task_struct里);2.很好的缺页中断处理机制。
这样,我们只需要把要挂靠的进程的mm_struct设置到当前进程的task_struct的mm里面就是了,这样在实际访问时会从mm_struct 里面得到页全局目录,从而访问叶面或处理缺页,而缺页处理也是首先得到当前进程的mm_struct结构从而可以得到pgd,这个设计简直太好了,妙!
不光这里受惠,在进程切换的时候可以首先查看两个task_struct的mm_struct是否一致,一致的话就是线程切换,不切换cr3硬件环境,不同时再切换。
linux这么好的 数据结构设计使得很多操作同时受惠,一脉相承。所以说linux的进程实现既轻量又高效!
static void use_mm(struct mm_struct *mm)
{
struct mm_struct *active_mm;
struct task_struct *tsk = current;
task_lock(tsk);
tsk->flags |= PF_BORROWED_MM;
active_mm = tsk->active_mm;
atomic_inc(&mm->mm_count);
tsk->mm = mm;
tsk->active_mm = mm;
/*
* Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise
* it won't work. Update it accordingly if you change it here
*/
activate_mm(active_mm, mm);
task_unlock(tsk);
mmdrop(active_mm);
}
static void unuse_mm(struct mm_struct *mm)
{
struct task_struct *tsk = current;
task_lock(tsk);
tsk->flags &= ~PF_BORROWED_MM;
tsk->mm = NULL;
/* active_mm is still 'mm' */
enter_lazy_tlb(mm, tsk);
task_unlock(tsk);
}
不过如果你实在看不出这到底比windows好在哪,我就没有办法了,好好感受!这代码多么简洁,如果你还是不明白,那么和KeAttachProcess比较一下吧