zoukankan      html  css  js  c++  java
  • Kernel rest_init相关

    Linux系统里,有些进程只有kernel部分的代码,即由一个kernel函数进入,在sched的时候,将其与用户进程同等对待。

    PID为0的叫swapper或sched进程,对应函数为rest_init

    init进程PID为1,

    kthreadd进程PID为2,

    0号进程,即rest_init主体如下

     1 static noinline void __init_refok rest_init(void)
     2 {
     3     int pid;
     4 
     5     rcu_scheduler_starting();
     6     smpboot_thread_init();
     7     /*
     8      * We need to spawn init first so that it obtains pid 1, however
     9      * the init task will end up wanting to create kthreads, which, if
    10      * we schedule it before we create kthreadd, will OOPS.
    11      */
    12     kernel_thread(kernel_init, NULL, CLONE_FS);
    13     numa_default_policy();
    14     pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
    15     rcu_read_lock();
    16     kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
    17     rcu_read_unlock();
    18     complete(&kthreadd_done);
    19 
    20     /*
    21      * The boot idle thread must execute schedule()
    22      * at least once to get things moving:
    23      */
    24     init_idle_bootup_task(current);
    25     schedule_preempt_disabled();
    26     /* Call into cpu_idle with preempt disabled */
    27     cpu_startup_entry(CPUHP_ONLINE);

    先是rcu_scheduler_starting函数,这个函数的作用是

    再是smpboot_thread_init函数,这个函数注册smpboot时候的notifier,响应CPU动作

    1 static struct notifier_block smpboot_thread_notifier = {
    2     .notifier_call = smpboot_thread_call,
    3     .priority = CPU_PRI_SMPBOOT,
    4 };
    5 
    6 void __cpuinit smpboot_thread_init(void)
    7 {
    8     register_cpu_notifier(&smpboot_thread_notifier);
    9 }

     然后调用kernel_thread函数fork init进程

    1 /*
    2  * Create a kernel thread.
    3  */
    4 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
    5 {
    6     return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
    7         (unsigned long)arg, NULL, NULL);
    8 }


    do_fork函数被调用

    这里有一点要注意,init进程执行的时候要等kerneladd进程执行后才被complete(&kthreadd_done)唤醒,然后真正执行,不然直接调度到init的话会OOPs

    numa_default_policy被调用设置内存numa默认策略

    然后调用kernel_thread函数fork kthreadd进程

    然后用find_task_by_pid_ns(pid, &init_pid_ns)获取kthreadd的task_struct

    最后唤醒complete(&kthreadd_done)进程

    最后,0号进程,即空闲进程,要让一切跑起来,调用一次schedule

  • 相关阅读:
    HDU 1941 Justice League
    HDU 1960 Taxi Cab Scheme
    POJ 1986 Distance Queries
    UVA 11991 Easy Problem from Rujia Liu?
    sql的跟踪与Tkprof工具
    ORA04031 错误
    Oracle_spatial的空间索引
    oracle发生重启动的介绍
    expdp\impdp及exp\imp
    oracle锁
  • 原文地址:https://www.cnblogs.com/cascle/p/5920134.html
Copyright © 2011-2022 走看看