Linux 启动流程 粗解(二)

另一个重要函数 在 start_kernel中最后调用的函数 0# 1#进程都是在这里启动的

static noinline void __init_refok rest_init(void) __releases(kernel_lock)

{
    int pid;

    rcu_scheduler_starting();
    /*
     * We need to spawn init first so that it obtains pid 1, however
     * the init task will end up wanting to create kthreads, which, if
     * we schedule it before we create kthreadd, will OOPS.
     */
    kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
    numa_default_policy();
    pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
    rcu_read_lock();
    kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
    rcu_read_unlock();
    complete(&kthreadd_done);
    unlock_kernel();

    /*
     * The boot idle thread must execute schedule()
     * at least once to get things moving:
     */
    init_idle_bootup_task(current);
    preempt_enable_no_resched();
    schedule();
    preempt_disable();

    /* Call into cpu_idle with preempt disabled */
    cpu_idle();
}

 

 

static int __init kernel_init(void * unused)
{
    /*
     * Wait until kthreadd is all set-up. kernel_init()函数等待kthreadd_done条件完成再开始启动。
     */
    wait_for_completion(&kthreadd_done);
    lock_kernel();

    /*
     * 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);
    /*
     * Tell the world that we're going to be the grim
     * reaper of innocent orphaned children.
     *
     * We don't want people to have to make incorrect
     * assumptions about where in the task array this
     * can be found.
     */
    init_pid_ns.child_reaper = current;

 

    /*

     * When the value in this file is 0 (the default), ctrl-alt-del is trapped and sent to the init program to handle a  

     * graceful restart (or to the PID of your choice, which you can configure with cad_pid tunable). However, when the

     * value is greater that zero, Linux's reaction to this key combination will be an immediate reboot, without syncing

     * its dirty buffers.

     * When a program (like dosemu) has the keyboard in raw mode, the ctrl-alt-del is intercepted by the program

     * before it ever reaches the kernel tty layer, and it is up to the program to decide what to do with it.

     */

    cad_pid = task_pid(current);

    smp_prepare_cpus(setup_max_cpus);

    do_pre_smp_initcalls();

------------------------------------
    start_boot_trace();
    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;
}

 

static void __init do_pre_smp_initcalls(void)
{
    initcall_t *fn;

    for (fn = __initcall_start; fn < __early_initcall_end; fn++)
        do_one_initcall(*fn);
}

c002d328 T __initcall_start
c002d328 T __setup_end
c002d32c t __initcall_spawn_softlockup_taskearly
c002d330 t __initcall_relay_initearly
c002d334 T __early_initcall_end

 

sched_init_smp()->sched_init_granularity()->update_sysctl()

static void update_sysctl(void)
{
    unsigned int factor = get_update_sysctl_factor();

#define SET_SYSCTL(name) /
    (sysctl_##name = (factor) * normalized_sysctl_##name)
    SET_SYSCTL(sched_min_granularity);
    SET_SYSCTL(sched_latency);
    SET_SYSCTL(sched_wakeup_granularity);
    SET_SYSCTL(sched_shares_ratelimit);
#undef SET_SYSCTL
}

c06863c0 D sysctl_sched_min_granularity
c06863c4 D normalized_sysctl_sched_min_granularity
c06863c8 D sysctl_sched_latency
c06863cc D normalized_sysctl_sched_latency
c06863d0 D sysctl_sched_wakeup_granularity
c06863d4 D normalized_sysctl_sched_wakeup_granularity
c06863d8 D sysctl_sched_shares_ratelimit
c06863dc D normalized_sysctl_sched_shares_ratelimit

 

/*
 * Ok, the machine is now initialized. None of the devices
 * have been touched yet, but the CPU subsystem is up and
 * running, and memory and process management works.
 * CPU已经running,存储器和进程管理也已工作。
 * Now we can finally start doing some real work.. 开始干一些实际的工作了。。。
 */
static void __init do_basic_setup(void)
{
    init_workqueues();
    cpuset_init_smp();
    usermodehelper_init();
    init_tmpfs();
    driver_init();
    init_irq_proc();
    do_ctors();
    do_initcalls();
}

 

void __init usermodehelper_init(void)
{
    khelper_wq = create_singlethread_workqueue("khelper");
    BUG_ON(!khelper_wq);
}

Linux has various parts of the hotplug subsystem and events subsystem, which work together when a new device is inserted before it becomes available. Linux has a permanent kernel_thread helper running called khelper . This thread is occasionally used as a schedulable context for stuff that call_usermode_helper wants to run - like /sbin/hotplug or modprobe. It’s a pretty cool solution to the problem of calling out to userspace for help. khelper is responsible for running up hotplug when I insert my wifi card, which then configures the netdevice and hooks up ifplugd to watch for net events.

 

static void __init do_initcalls(void)
{
    initcall_t *fn;

    for (fn = __early_initcall_end; fn < __initcall_end; fn++)
        do_one_initcall(*fn);

    /* Make sure there is no pending stuff from the initcall sequence */
    flush_scheduled_work();
}

c002d328 T __initcall_start
c002d328 T __setup_end
c002d32c t __initcall_spawn_softlockup_taskearly
c002d330 t __initcall_relay_initearly
c002d334 T __early_initcall_end
c002d334 t __initcall_init_mmap_min_addr0
c002d338 t __initcall_init_cpufreq_transition_notifier_list0
c002d33c t __initcall_net_ns_init0
c002d340 t __initcall_ptrace_break_init1
c002d344 t __initcall_consistent_init1

..........................................................

c002db5c t __initcall_tcp_congestion_default7
c002db60 t __initcall_msm_pm_init7s
c002db64 t __initcall_initialize_hashrnd7s
c002db68 T __con_initcall_start
c002db68 t __initcall_con_init
c002db68 T __initcall_end

 

call the .init function to init the linked to kernel modules.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值