process 1

来源:互联网 发布:网络推广团队口号 编辑:程序博客网 时间:2024/06/06 05:47

init process 是如何创建的?

start_kernel -> rest_init -> kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);


static int __init kernel_init(void * unused)
{
    /*
     * Wait until kthreadd is all set-up.
     */
    wait_for_completion(&kthreadd_done);
    /*
     * init can allocate pages on any node
     */
    set_mems_allowed(node_states[N_HIGH_MEMORY]);
    /*
     * init can run on any cpu.
     */
    set_cpus_allowed_ptr(current, cpu_all_mask);

    cad_pid = task_pid(current);

    smp_prepare_cpus(setup_max_cpus);

    do_pre_smp_initcalls();
    lockup_detector_init();

    smp_init();
    sched_init_smp();

    do_basic_setup();

    /* Open the /dev/console on the rootfs, this should never fail */
    if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
        printk(KERN_WARNING "Warning: unable to open an initial console.\n");

    (void) sys_dup(0);
    (void) sys_dup(0);
    /*
     * check if there is an early userspace init.  If yes, let it do all
     * the work
     */

    if (!ramdisk_execute_command)
        ramdisk_execute_command = "/init";

    if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
        ramdisk_execute_command = NULL;
        prepare_namespace();
    }

    /*
     * Ok, we have completed the initial bootup, and
     * we're essentially up and running. Get rid of the
     * initmem segments and start the user-mode stuff..
     */

    init_post();
    return 0;
}



/* This is a non __init function. Force it to be noinline otherwise gcc
 * makes it inline to init() and it becomes part of init.text section
 */
static noinline int init_post(void)
{
    /* need to finish all async __init code before freeing the memory */
    async_synchronize_full();
    free_initmem();
    mark_rodata_ro();
    system_state = SYSTEM_RUNNING;
    numa_default_policy();


    current->signal->flags |= SIGNAL_UNKILLABLE;

    if (ramdisk_execute_command) {
        run_init_process(ramdisk_execute_command);
        printk(KERN_WARNING "Failed to execute %s\n",
                ramdisk_execute_command);
    }

    /*
     * We try each of these until one succeeds.
     *
     * The Bourne shell can be used instead of init if we are
     * trying to recover a really broken machine.
     */
    if (execute_command) {
        run_init_process(execute_command);
        printk(KERN_WARNING "Failed to execute %s.  Attempting "
                    "defaults...\n", execute_command);
    }
    run_init_process("/sbin/init");
    run_init_process("/etc/init");
    run_init_process("/bin/init");
    run_init_process("/bin/sh");

    panic("No init found.  Try passing init= option to kernel. "
          "See Linux Documentation/init.txt for guidance.");
}
这里
crash> execute_command
execute_command = $6 = 0xc0e4b0fe "/init"
所以调用
static void run_init_process(const char *init_filename)
{
    argv_init[0] = init_filename;
    kernel_execve(init_filename, argv_init, envp_init);
}

看这两个全局变量argv_init and envp_init.

crash> argv_init
argv_init = $7 =
 {0xc0e4b0fe "/init", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
crash> envp_init
envp_init = $8 =
 {0xc060c198 "HOME=/", 0xc060c19f "TERM=linux", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
这两个全局变量也可从:
crash> ps -a 1
PID: 1      TASK: e6828bc0  CPU: 0   COMMAND: "init"
ARG: /init
ENV: HOME=/
     TERM=linux

如果是内核进程会显示:

crash> ps -a 0
PID: 0      TASK: c06f2fd8  CPU: 0   COMMAND: "swapper/0"
ps: no user stack

执行用户空间进程

run_init_process(“/init”);

int kernel_execve(const char *filename,
          const char *const argv[],
          const char *const envp[])
{
    struct pt_regs regs;
    int ret;

    memset(&regs, 0, sizeof(struct pt_regs));
    ret = do_execve(filename,
            (const char __user *const __user *)argv,
            (const char __user *const __user *)envp, &regs);
    if (ret < 0)
        goto out;

    /*
     * Save argc to the register structure for userspace.
     */
    regs.ARM_r0 = ret;

    /*
     * We were successful.  We won't be returning to our caller, but
     * instead to user space by manipulating the kernel stack.
     */
    asm(    "add    r0, %0, %1\n\t"
        "mov    r1, %2\n\t"
        "mov    r2, %3\n\t"
        "bl    memmove\n\t"    /* copy regs to top of stack */
        "mov    r8, #0\n\t"    /* not a syscall */
        "mov    r9, %0\n\t"    /* thread structure */
        "mov    sp, r0\n\t"    /* reposition stack pointer */
        "b    ret_to_user"
        :
        : "r" (current_thread_info()),
          "Ir" (THREAD_START_SP - sizeof(regs)),
          "r" (&regs),
          "Ir" (sizeof(regs))
        : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");

 out:
    return ret;
}