我正在创建一个内核模块来查找所有进程的驻留页面。我正在使用get_mm_rss()
和for_each_process,但它有效只有对于init进程/第一次迭代后的第一次,它不工作
int __init schedp(void){
struct task_struct *p;
for_each_process(p) {
int pid = task_pid_nr(p);
printk("Process: %s (pid = %d) , (rpages : %lu)n",
p->comm, pid, get_mm_rss(p->mm));
}
return 0;
}
结果:
BUG: unable to handle kernel NULL pointer dereference at 00000160,
您可能在p->mm
中获得NULL
,因为有些任务可能具有无效的mm
指针,因为它们正在退出或没有mm
(因为它们是内核线程,不确定)。
当你对如何使用内核API感到困惑时,总是在内核本身中寻找示例。通过交叉参考工具快速搜索我找到了kernel/cpu.c:
for_each_process(p) {
struct task_struct *t;
/*
* Main thread might exit, but other threads may still have
* a valid mm. Find one.
*/
t = find_lock_task_mm(p);
if (!t)
continue;
cpumask_clear_cpu(cpu, mm_cpumask(t->mm));
task_unlock(t);
}
请注意,您需要调用find_lock_task_mm()
和task_unlock()
,并显式检查NULL
。
最后,它在创建一个函数后工作,该函数检查mm_struct是否有效
struct task_struct *task_mm(struct task_struct *p){
struct task_struct *t;
rcu_read_lock();
for_each_thread(p, t) {
task_lock(t);
if (likely(t->mm))
goto found;
task_unlock(t);
}
t = NULL;
found:
rcu_read_unlock();
return t;
}