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\n",
 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...\n", 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的初始化就完成了。

此时,中断和中断驱动的进程调度机制,调度着各个线程在各个CPU上的运行。
中断处理程序不时被触发。
操作系统上,一些内核线程在内核态运行,它们永远不会进入用户态。它们也根本没有用户态的内存空间。它的线性地址空间就是共享内核的线性地址空间。
一些用户进程通常在用户态运行。有时因为系统调用而进入内核态,调用内核提供的系统调用处理函数。


         但有时,我们的内核模块或者内核线程希望能够调用用户空间的进程,就像系统启动之初init_post函数做的那样。

       如,一个驱动从内核得到了主从设备号,然后需要使用mknod命令创建相应的设备文件,以供用户调用该设备。

       如,一个内核线程想神不知鬼不觉地偷偷运行个有特权的后门程序。

等等之类的需求。

call_usermodehelper函数

          Linux  Kernel提供了call_usermodehelper函数,让我们能够异常方便地在内核中直接新建和运行用户空间程序,并且该程序具有root权限。



call_usermodehelper函数源码 include/linux/kmod.h头文件

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwjxsp.html