Linux内核模块冻结计算机,同时迭代运行的进程以访问进程打开的文件

时间:2013-05-12 12:40:35

标签: c module linux-kernel

我正在使用内核版本3.x开发内核模块。

我有一个函数负责确定正在运行的进程是否打开了给定文件。

这是我的代码(请参阅我之后的评论):

struct task_struct *    process = NULL;
struct files_struct *   task_files = NULL;
struct fdtable *        fdt = NULL;
int                     fd_i;
char                    tmpbuf[256];
char *                  process_path = "";

for_each_process(process)
{
    // Ignore processes without files
    if (process->files == NULL)
        continue;

    printk(KERN_INFO "task_lock()...\n");
    task_lock(process);
    printk(KERN_INFO "task_lock() DONE\n");
    task_files = process->files;
    printk(KERN_INFO "task_unlock()...\n");
    task_unlock(process);
    printk(KERN_INFO "task_unlock() DONE\n");

    printk(KERN_INFO "files_fdtable()...\n");
    fdt = files_fdtable(task_files);
    printk(KERN_INFO "files_fdtable() DONE\n");

    printk(KERN_INFO "Iterating files...\n");
    for (fd_i = 0; fd_i < fdt->max_fds; fd_i++)
    {
        if (fcheck_files(task_files, fd_i) == my_file)
        {
            if (process->mm)
            {
                if (process->mm->exe_file)
                {

                    process_path = d_path(&process->mm->exe_file->f_path, tmpbuf, sizeof(tmpbuf));
                    break;
                } else {
                    printk(KERN_INFO "process->mm->exe_file is NULL\n");
                }
            } else {
                printk(KERN_INFO "process->mm is NULL\n");
            }
        }
    }
    printk(KERN_INFO "Files iteration finished\n");
}

此代码正常运行,变量process_path包含打开给定文件的进程的路径。 但是当机器上有很大的负载时(因此经常会经过这段代码),机器冻结(经过一段时间后)和最新的打印调试是:

task_unlock() DONE

然后我看不出我做错了什么。

请您解释一下为什么我的代码冻结机器以及如何修复它?

3 个答案:

答案 0 :(得分:1)

您设计模块的方式是负责系统冻结。请注意,您已经使用了for_each_process(),这意味着它将遍历系统的每个进程。因此,当您在系统上加载时,进程数量会变大。此外,在你的for_each_process()循环中,你正在调用task_lock / unlock()并尝试对进程进行各种操作,所有这些操作都很昂贵,因为它们都有自己的锁。当系统负载较低时,它们并不明显,但随着系统负载越来越多,模块运行时的复杂性也会增加,但在低负载时仍然不太明显。我建议使用像ftrace这样的功能来检测你的模块,同时避免过度使用printk(因为printk也需要安排,klogd用于此目的)。并且在低负载下检查模块在内核中的运行方式。测量它在每个循环上花费的时间,你了解自己。内核是一个大野兽,里面发生了很多事情......

答案 1 :(得分:0)

尝试以下方法:

read_lock(&tasklist_lock);

do_each_thread(g, p) {
  task_lock(p);

  if (check_for_file(p, file)) {
    task_unlock(p);
    goto next;
  }

  task_unlock(p);
} while_each_thread(g, p);

next:

read_unlock(&tasklist_lock);

答案 2 :(得分:-1)

我终于修复了我的代码。

我首先实现了对链接列表中进程和打开文件之间关系的一种缓存,并在多个方法中重新考虑了我的代码(并且在修复了内存泄漏之后),它现在正在工作。

谢谢大家的帮助。