Linux主循环与rest_init()

操作系统的主循环

Linux 操作系统的主循环是指内核(kernel)的主要执行循环,它负责处理各种系统事件和调度任务。主循环的实现可以因不同的内核版本和配置而有所不同,但通常包括以下几个关键步骤:

  1. 事件等待:主循环会通过相应的机制(如中断控制器、系统调用接口)等待各种事件的发生,例如中断、系统调用、定时器到期等。它会监测和等待这些事件,并根据事件的类型和优先级进行处理。
    
  2. 事件处理:当事件发生时,主循环会调用相应的事件处理程序来处理它们。例如,对于中断事件,内核会调用中断处理程序来响应中断;对于系统调用事件,内核会调用系统调用处理程序来执行用户空间的请求。
    
  3. 调度任务:一旦处理完当前事件,主循环会根据一定的调度策略,从就绪队列中选择一个最合适的任务来运行。这涉及到任务的优先级、时间片分配、调度类别等因素的考量。
    
  4. 任务执行:被选中的任务会在处理器上执行一段时间,直到它主动放弃处理器或被某个事件中断。任务的执行包括执行指令、访问内存、操作设备等操作。
    
  5. 系统维护:主循环会进行各种系统维护任务,例如内存管理、文件系统管理、设备管理等。这些任务涉及到内核数据结构的维护、资源的分配和回收、状态的更新等。
    
  6. 循环重复:一旦当前任务的时间片用尽或被中断,主循环会重新回到开头,等待下一个事件的发生,并选择下一个要运行的任务。
    

通过不断地循环执行上述步骤,主循环能够实现多任务的管理和调度,以及对系统的各种事件和需求的响应。它是内核运行的核心,保证了内核能够有效地管理和利用系统资源,并提供稳定和可靠的系统运行环境。

rest_init()

static noinline void __init_refok rest_init(void)                                                                                           
{                                                                                                                                           
        int pid;                                                                                                                            
                                                                                                                                            
        rcu_scheduler_starting();      
        // 调用 RCU(Read-Copy-Update)子系统的函数,用于初始化 RCU 调度器   
                                                                                              
        /*                                                                                                                                  
         * 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);                                                                         
        // 创建 kernel_init 进程:通过调用 kernel_thread 函数,创建一个新的内核线程,该线程的入口点是 kernel_init 函数。这个进程将成为系统的初始化进程。
        numa_default_policy();                                                                                                             
        pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);   
        // 创建 kthreadd 进程:同样通过 kernel_thread 函数,创建一个新的内核线程,入口点为 kthreadd 函数。这个进程负责创建其他内核线程。                                                                                
        rcu_read_lock();                                                                                                                    
        kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);                                                                             
        rcu_read_unlock();                                                                                                                  
        complete(&kthreadd_done);                                                                                                           
                                                                                                                                            
        /*                                                                                                                                  
         * The boot idle thread must execute schedule()                                                                                     
         * at least once to get things moving:                                                                                              
         */                                                                                                                                 
        init_idle_bootup_task(current);                                                                                                   
        schedule_preempt_disabled();                                                                                     
        /* Call into cpu_idle with preempt disabled */                                                                                      
        cpu_startup_entry(CPUHP_ONLINE);   

        // 在禁用抢占的情况下调用上面初始化的idle进程。                                                                                   
}

代码说明:

numa_default_policy():初始化 NUMA(Non-Uniform Memory Access)策略,用于管理多个 NUMA 节点的内存访问。

rcu_read_lock() 和 rcu_read_unlock():通过读取锁定机制保护 RCU 数据结构,以避免并发访问的问题。

find_task_by_pid_ns():根据进程 ID 查找相应的任务结构体,返回指向 kthreadd 进程的任务指针。

complete(&kthreadd_done):标记 kthreadd 进程已经完成了初始化。

schedule_preempt_disabled():将当前任务放入调度队列,使得系统能够调度其他任务执行。

cpu_startup_entry(CPUHP_ONLINE):通知 CPU 热插拔子系统,当前 CPU 已在线,可以进行后续的初始化操作。

这段代码主要是在系统启动过程中,初始化了一些关键的内核组件和进程,以确保系统能够正常运行。其中,kernel_init 进程成为系统的初始化进程,而 kthreadd 进程负责创建其他内核线程。这些进程和组件的初始化是为了建立起基本的系统环境,为后续的任务和用户程序的执行做准备。

posted @ 2023-08-04 12:12  武平宁  阅读(212)  评论(0)    收藏  举报