• [linux]进程(三)——idle进程


    9,linux进程切换

    进程切换:
    基本概念:
    进程上下文:当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,运行于进程上下文的进程是可以被抢占的。
    硬件上下文:进程恢复执行前必须载入寄存器的一组数据称为硬件上下文
    linux内核在进程切换的时候是并不区分进程和线程的~因为切换是针对task,
    进程切换的时机:一般是在系统调用或者中断的时候,发生在内核态。
    进程切换过程:
    进程切换统一发生在schedule()函数中,核心函数是context_switch()函数,代码位置:kernel/kernel/sched/Core.c文件,以ARM为基础讲解linux进程的切换:linux进程切换过程,schedule()函数代码分析:schedule()代码分析 schedule代码分析二

    10,idle进程

    idle进程的概念:
    简单的说idle是一个进程,其pid号为 0。其前身是系统创建的第一个进程,也是唯一一个没有通过fork()产生的进程。在smp系统中,每个处理器单元有独立的一个运行队列,而每个运行队列上又有一个idle进程,即有多少处理器单元,就有多少idle进程。系统的空闲时间,其实就是指idle进程的"运行时间"。idle进程pid==o,也就是init_task.


    idle进程的创建:
    vmlinux的入口是arch/arm/kernel/head.S,(关注ENTRY(stext)的位置)入口地址可以从kernel/arch/arm/kernel/vmlinux.lds.S得知文件,在该汇编文件中为pid为0的原始进程设置了执行环境,包括先禁止MMU,内核刚开始是用物理地址的,禁止I-Cache和D-Cache,然后读取RO,R1,R2,然后原是进程开始执行start_kernel()完成Linux内核的初始化工作。包括初始化页表,初始化中断向量表,初始化系统时间等。继而调用 fork(),创建第一个用户进程: 创建init进程(pid==1)的函数如下:
    kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
    pid为1的init进程,它会继续完成剩下的初始化工作,然后execve(/sbin/init), 成为系统中的其他所有进程的祖先,pid为0的idle进程在创建了init进程后,pid=0的进程调用 cpu_idle()演变成了idle进程。current_thread_info()->status |= TS_POLLING;init在演变成/sbin/init之前,会执行一部分初始化工作,其中一个就是 smp_prepare_cpus(),初始化SMP处理器,在这过程中会在处理每个从处理器时调用 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0); init_idle(task, cpu);
     
    idle进程的运行时机:
    idle进程优先级为MAX_PRIO,即最低优先级。早先版本中,idle是参与调度的,所以将其优先级设为最低,当没有其他进程可以运行时,才会调度执行idle,而目前的版本中idle并不在运行队列中参与调度,而是在运行队列结构中含idle指针,指向idle进程,在调度器发现运行队列为空的时候运行,调入运行  


    idle进程到底做了什么:
    idle进程最终调用了cpu_idle()函数

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. process.c  
    2. void cpu_idle(void)  
    3. {  
    4.     ......  
    5.     /* endless idle loop with no priority at all */  
    6.     while (1) {  
    7.         ......  
    8.         while (!need_resched()) {  
    9.             if (cpu_is_offline(smp_processor_id())) {  
    10.                 tick_set_cpu_plugoff_flag(1);  
    11.                 cpu_die(); /* plugoff CPU */  
    12.             }  
    13.             ......  
    14.             if (cpuidle_idle_call())  
    15.                 pm_idle(); /* 进入低电 */  
    16.         }  
    17.         ......  
    18.         schedule_preempt_disabled(); /* 调用schedule() */  
    19.     }  
    20. }  

    补充:linux kernel的启动流程
    当嵌入式设备从uboot跳转到kernel的时候,首先运行的是kernel的自解压程序,linux内核在编译后是以压缩文件形式存在,路径是kernel/out/arch/arm/boot/zImage
    zImage里的代码和数据是如何存放的,答:根据out/arch/arm/boot/compressed/vmlinux.lds文件,如果要修改代码段和数据段位置也需要修改该链接脚本。
    kernel init的基本流程如下:
         .stext 
          start_kernel() 
          rest_init() 
          kernel_init() 

  • 相关阅读:
    RedHat 7.0及CentOS 7.0禁止Ping的三种方法
    修改WordPress后台默认登陆地址提高网站安全性
    解决WordPress用户名密码都正确但点击登陆就清空密码的问题
    Windows上使用Git托管代码到Coding
    使用Coding Pages托管网站
    Windows上设置Mozilla Thunderbird邮件客户端后台运行
    在VirtualBox中安装BlackArch Linux
    关于XML学习
    软件工程课程设计团队项目总结与项目报告
    详细设计
  • 原文地址:https://www.cnblogs.com/zhiliao112/p/4051361.html
Copyright © 2020-2023  润新知