如何从内核空间调用用户空间程序

来源:互联网 发布:软件需求分析模板 编辑:程序博客网 时间:2024/05/17 03:55

在include/linux/kmod.h中,我们可以找到API函数call_usermodehelper定义:

static inline intcall_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)

{

...

}

它实际上是调用了kernel/kmod.c中定义的函数call_usermodehelper_exec,有关细节可以去看一下kmod.c中的实现,下面

我们仅仅分析在不同的上下文中如何使用这个API,该函数提供char *path, char **argv, char **envp 这些指针,

以及enum umh_wait wait(一个枚举类型:不等待、等待进程被执行及等待进程完全结束)这几个参数。


下面从一个实例来演示一下如何使用该API:

static int do_sendlog_user(int port, u32 link, u32 duplex, u32 speed)
{
        static char *speed_desc[] = {"10","100","1000","0"};
        static char *log_path = "/usr/sbin/do_sendlog.sh";
        static char *log_envp[] = { "HOME=/",
                                    "TERM=linux",
                                    "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
                                    NULL };
        char arg_type[32];
        char arg_port[32];
        char arg_link[32];
        char arg_duplex[32];
        char arg_speed[32];
        char *log_argv[] = { log_path,
                             arg_type,
                             arg_port,
                             arg_link,
                             arg_duplex,
                             arg_speed,
                             NULL};

        strcpy(arg_type, "PORT_STATUS");
        sprintf(arg_port, "%u", port);
        sprintf(arg_link, "%s", link ? "linkup" : "linkdown");
        sprintf(arg_duplex, "%s", duplex ? "fdx" : "hdx");
        sprintf(arg_speed, "%s", speed_desc[speed]);

        printk("%s port %d, link %d, duplex %d, speed %d\n", __FUNCTION__, port, link, duplex, speed);
        call_usermodehelper(log_path, log_argv, log_envp, UMH_WAIT_EXEC);
        return 0;
}

值得注意的是最后一个参数,enum umh_wait wait有以下几个值,它们都会创建一个内核线程来异步执行用户空间程序,只是在同步的方式上有所区别:

UMH_NO_WAIT:立即返回,可以用于中断上下文中,如果在进程上下文中,会出现调用者所在函数已经回收局部变量后用户程序都仍未执行的情况,

   这时所传递的其它参数可能会是一个无法确定的值,

UMH_WAIT_EXEC:用户空间程序执行则立即返回

UMH_WAIT_PROC:等待用户程序执行完毕再返回


对于我个人的应用场合来说,大多选择UMH_WAIT_EXEC模式,既不会阻塞于用户空间程序,也不会出现参数传递失败的情况


原创粉丝点击