如何在内核模块中使用proc_pid_cmdline

我正在编写一个内核模块来获取具有完整进程名称的pid列表。 proc_pid_cmdline()给出了完整的进程名称;使用相同的函数/proc/*/cmdline获取完整的进程名称。 (struct task_struct) -> comm提示它是什么进程,但不是完整的path。

我已经包含了函数的名字,但是由于它不知道在哪里find这个函数,所以会出错。

如何在模块中使用proc_pid_cmdline()

你不应该调用proc_pid_cmdline()

这是fs/proc/base.c一个非公共函数 :

 static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task) 

但是,它所做的很简单:

 get_cmdline(task, m->buf, PAGE_SIZE); 

这不太可能返回完整的路径,并且不可能在每种情况下确定完整路径。 arg [0]值可能会被覆盖,文件可能被删除或移动等。一个进程可能会以一种使原来的命令行模糊的方式,以及各种其他的弊病。

对Fedora 20系统/ proc / * / cmdline的扫描发现了各种不太有用的结果:

 -F BUG: WARNING: at WARNING: CPU: INFO: possible recursive locking detecte ernel BUG at list_del corruption list_add corruption do_IRQ: stack overflow: ear stack overflow (cur: eneral protection fault nable to handle kernel ouble fault: RTNL: assertion failed eek! page_mapcount(page) went negative! adness at NETDEV WATCHDOG ysctl table check failed : nobody cared IRQ handler type mismatch Machine Check Exception: Machine check events logged divide error: bounds: coprocessor segment overrun: invalid TSS: segment not present: invalid opcode: alignment check: stack segment: fpu exception: simd exception: iret exception: /var/log/messages -- /usr/bin/abrt-dump-oops -xtD 

我已经设法解决了这个问题的一个版本 。 我想访问所有PID的cmdline ,但在内核本身(而不是内核模块作为问题状态),但也许这些原则也可以应用到内核模块?

我做的是,我添加了以下函数fs/proc/base.c

 int proc_get_cmdline(struct task_struct *task, char * buffer) { int i; int ret = proc_pid_cmdline(task, buffer); for(i = 0; i < ret - 1; i++) { if(buffer[i] == '\0') buffer[i] = ' '; } return 0; } 

然后我在include/linux/proc_fs.h添加声明
int proc_get_cmdline(struct task_struct *, char *);

此时,我可以访问内核中所有进程的cmdline 。 要访问task_struct ,也许你可以参考kernel:通过pid找到task_struct的有效方法? 。

一旦你有task_struct ,你应该能够做到这样的事情:

 char cmdline[256]; proc_get_cmdline(task, cmdline); if(strlen(cmdline) > 0) printk(" cmdline :%s\n", cmdline); else printk(" cmdline :%s\n", task->comm); 

我能够以这种方式获得所有进程的命令行。

获取进程背后的二进制文件的完整路径。

 char * exepathp; struct file * exe_file; struct mm_struct *mm; char exe_path [1000]; //straight up stolen from get_mm_exe_file mm = get_task_mm(current); down_read(&mm->mmap_sem); //lock read exe_file = mm->exe_file; if (exe_file) get_file(exe_file); up_read(&mm->mmap_sem); //unlock read //reduce exe path to a string exepathp = d_path( &(exe_file->f_path), exe_path, 1000*sizeof(char) ); 

当前是您感兴趣的进程的任务结构。变量exepathp获取完整路径的字符串。 这与进程cmd稍有不同,这是加载启动进程的二进制文件的路径。 将这个路径与进程cmd结合起来应该会给你完整的路径。