内核启动用户态的应用程序是通过call_usermodehelper来调用的,比较常见的调用,比如modprobe.
参数说明;
path : 应用程序的位置
argv : 传递给用户态应用程序的参数
envp: 传递给应用程序的环境变量
wait : 调用用户态应用程序的内核程序是否等到用户态程序退出后才退出。
使用的例子:
我们来看kmod.c的源码,它通过调用用户态的modprobe来加载所需要的驱动模块。
- static inline int
- call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
参数说明;
path : 应用程序的位置
argv : 传递给用户态应用程序的参数
envp: 传递给应用程序的环境变量
wait : 调用用户态应用程序的内核程序是否等到用户态程序退出后才退出。
使用的例子:
我们来看kmod.c的源码,它通过调用用户态的modprobe来加载所需要的驱动模块。
- int request_module(const char *fmt, ...)
- {
- va_list args;
- char module_name[MODULE_NAME_LEN];
- unsigned int max_modprobes;
- int ret;
- ///构造传递给modeprobe的参数
- char *argv[] = { modprobe_path, "-q", "--", module_name, NULL };
- static char *envp[] = { "HOME=/",
- "TERM=linux",
- "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
- NULL };
- static atomic_t kmod_concurrent = ATOMIC_INIT(0);
- #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
- static int kmod_loop_msg;
- va_start(args, fmt);
- ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
- va_end(args);
- if (ret >= MODULE_NAME_LEN)
- return -ENAMETOOLONG;
- /* If modprobe needs a service that is in a module, we get a recursive
- * loop. Limit the number of running kmod threads to max_threads/2 or
- * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
- * would be to run the parents of this process, counting how many times
- * kmod was invoked. That would mean accessing the internals of the
- * process tables to get the command line, proc_pid_cmdline is static
- * and it is not worth changing the proc code just to handle this case.
- * KAO.
- *
- * "trace the ppid" is simple, but will fail if someone's
- * parent exits. I think this is as good as it gets. --RR
- */
- max_modprobes = min(max_threads/2, MAX_KMOD_CONCURRENT);
- atomic_inc(&kmod_concurrent);
- if (atomic_read(&kmod_concurrent) > max_modprobes) {
- /* We may be blaming an innocent here, but unlikely */
- if (kmod_loop_msg++ < 5)
- printk(KERN_ERR
- "request_module: runaway loop modprobe %s\n",
- module_name);
- atomic_dec(&kmod_concurrent);
- return -ENOMEM;
- }
- ///调用modeprobe.
- ret = call_usermodehelper(modprobe_path, argv, envp, 1);
- atomic_dec(&kmod_concurrent);
- return ret;
- }