gpt4 book ai didi

c - 执行/调用用户空间程序,并从内核模块获取其 pid

转载 作者:IT王子 更新时间:2023-10-29 00:35:44 26 4
gpt4 key购买 nike

我 checkout Kernel APIs, Part 1: Invoking user - space applications from the kernel , 和 Executing a user-space function from the kernel space - Stack Overflow - 这是一个小的内核模块,callmodule.c,演示了:

// http://people.ee.ethz.ch/~arkeller/linux/code/usermodehelper.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>

static int __init callmodule_init(void)
{
int ret = 0;
char userprog[] = "/path/to/mytest";
char *argv[] = {userprog, "2", NULL };
char *envp[] = {"HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };

printk("callmodule: init %s\n", userprog);
/* last parameter: 1 -> wait until execution has finished, 0 go ahead without waiting*/
/* returns 0 if usermode process was started successfully, errorvalue otherwise*/
/* no possiblity to get return value of usermode process*/
ret = call_usermodehelper(userprog, argv, envp, UMH_WAIT_EXEC);
if (ret != 0)
printk("error in call to usermodehelper: %i\n", ret);
else
printk("everything all right\n");
return 0;
}

static void __exit callmodule_exit(void)
{
printk("callmodule: exit\n");
}

module_init(callmodule_init);
module_exit(callmodule_exit);
MODULE_LICENSE("GPL");

...使用Makefile:

obj-m += callmodule.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

当我通过 sudo insmod ./callmodule.ko && sudo rmmod callmodule 运行它时,我进入了 /var/log/syslog:

Feb 10 00:42:45 mypc kernel: [71455.260355] callmodule: init /path/to/mytest
Feb 10 00:42:45 mypc kernel: [71455.261218] everything all right
Feb 10 00:42:45 mypc kernel: [71455.286131] callmodule: exit

...这显然意味着一切顺利。 (使用 Linux 2.6.38-16-generic#67-Ubuntu SMP)

我的问题是 - 我怎样才能获得从内核模块实例化的进程的 PID?除了 call_usermodehelper 之外,是否有类似的进程允许我在内核空间中实例化用户空间进程并获取其 pid?


请注意,可能无法使用call_usermodehelper 并获取实例化的进程PID:

Re: call_usermodehelper's pid ? — Linux Kernel Newbies

I want to create a user space process from within a kernel module, and be able to kill it, send signals to it, etc...

can I know its pid ?

不,你不能。但是由于在实现内部 pid 是已知的, 使它可用的补丁不会太难(注意,错误 在内核中始终为负,pids 为正,限制为 2**16)。 不过,您必须修改所有期望 0 成功的调用方。

我查了一下资料,似乎最终有一个调用链:call_usermodehelper -> call_usermodehelper_setup -> __call_usermodehelper,看起来像:

static void __call_usermodehelper(struct work_struct *work)
{
struct subprocess_info *sub_info =
container_of(work, struct subprocess_info, work);
// ...
if (wait == UMH_WAIT_PROC)
pid = kernel_thread(wait_for_helper, sub_info,
CLONE_FS | CLONE_FILES | SIGCHLD);
else
pid = kernel_thread(____call_usermodehelper, sub_info,
CLONE_VFORK | SIGCHLD);
...

...所以使用了内核线程的PID,但它没有被保存;此外,work_structsubprocess_info 都没有 pid 字段(task_struct 有,但这里似乎没有使用 task_struct).记录这个 pid 需要更改内核源代码——我想避免这种情况,这就是为什么我也对 call_usermodehelper 以外的方法感兴趣的原因 ...

最佳答案

我对 kmod.c 中实现的理解的初步答案.

如果您查看 call_usermodehelper 的代码,您会看到它先调用 call_usermodehelper_setup,然后调用 call_usermodehelper_exec

call_usermodehelper_setup 将一个初始化函数作为参数,该函数将在 do_execve 之前执行。我相信执行 init 函数时 current 的值将为您提供用户进程的 task_struct

因此,要获取 pid,您需要:

  1. 在您的代码中复制 call_usermodehelper 的实现。
  2. 定义一个将作为参数传递给 call_usermodehelper_setup 的 init 函数。
  3. 在 init 函数中检索当前的 task_struct 和 PID。

关于c - 执行/调用用户空间程序,并从内核模块获取其 pid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21668727/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com