我正在编写一个内核模块来获取具有完整进程名称的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结合起来应该会给你完整的路径。