首页 / 操作系统 / Linux / 使用call_usermodehelper在Linux内核中直接运行用户空间程序
系统初始化时kernel_init在内核态创建和运行应用程序以完成系统初始化
内核刚刚启动时,只有内核态的代码,后来在init过程中,在内核态运行了一些初始化系统的程序,才产生了工作在用户空间的进程。 /* This is a non __init function. Force it to be noinline otherwise gcc 736 * makes it inline to init() and it becomes part of init.text section 737 */ 738static noinline int init_post(void) 739{ 740 /* need to finish all async __init code before freeing the memory */ 741 async_synchronize_full(); 742 free_initmem(); 743 mark_rodata_ro(); 744 system_state = SYSTEM_RUNNING; 745 numa_default_policy(); 746 747 748 current->signal->flags |= SIGNAL_UNKILLABLE; 749 750 if (ramdisk_execute_command) { 751 run_init_process(ramdisk_execute_command); 752 printk(KERN_WARNING "Failed to execute %s
", 753 ramdisk_execute_command); 754 } 755 756 /* 757 * We try each of these until one succeeds. 758 * 759 * The Bourne shell can be used instead of init if we are 760 * trying to recover a really broken machine. 从内核里发起系统调用,执行用户空间的应用程序。这些程序自动以root权限运行。 761 */ 762 if (execute_command) { 763 run_init_process(execute_command); 764 printk(KERN_WARNING "Failed to execute %s. Attempting " 765 "defaults...
", execute_command); 766 } 767 run_init_process("/sbin/init"); 768 run_init_process("/etc/init"); 769 run_init_process("/bin/init"); 770 run_init_process("/bin/sh"); 771 772 panic("No init found. Try passing init= option to kernel. " 773 "See Linux Documentation/init.txt for guidance."); 774} 这里,内核以此运行用户空间程序,从而产生了第一个以及后续的用户空间程序。 一般用户空间的init程序,会启动一个shell,供用户登录系统用。这样,这里启动的用户空间的程序永远不会返回。 也就是说,正常情况下不会到panic这一步。 系统执行到这里后,Linux Kernel的初始化就完成了。
50enum umh_wait { 51 UMH_NO_WAIT = -1, /* don"t wait at all */ 52 UMH_WAIT_EXEC = 0, /* wait for the exec, but not the process */ 53 UMH_WAIT_PROC = 1, /* wait for the process to complete */ 54}; 55 56struct subprocess_info { 57 struct work_struct work; 58 struct completion *complete; 59 char *path; 60 char **argv; 61 char **envp; 62 enum umh_wait wait; 63 int retval; 64 int (*init)(struct subprocess_info *info); 65 void (*cleanup)(struct subprocess_info *info); 66 void *data; 67}; 68
kernel/kmod.c实现文件377/** 378 * call_usermodehelper_exec - start a usermode application 379 * @sub_info: information about the subprocessa 子进程的信息 380 * @wait: wait for the application to finish and return status.等待用户空间子进程的完成,并返回结果。 381 * when -1 don"t wait at all, but you get no useful error back when 382 * the program couldn"t be exec"ed. This makes it safe to call 383 * from interrupt context. -1表示根本不等待子进程的结束。 但这样你就无法对程序出错进行处理。 如果使用中断上下文,那么应该使用-1。 384 * 385 * Runs a user-space application. The application is started 386 * asynchronously if wait is not set, and runs as a child of keventd. 387 * (ie. it runs with full root capabilities). call_usermodehelper_exec函数,启动一个用户模式应用程序。 如果不设置wait,那么用户空间应用程序会被异步启动。 它在root权限下运行。是keventd进程的子进程。