zoukankan      html  css  js  c++  java
  • 2020-2021-1 20209301《Linux内核原理与分析》第九周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)>
    这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第九周作业>
    这个作业的目标 <理解进程调度时机跟踪分析进程调度与进程切换的过程>
    作业正文 https://www.cnblogs.com/hyuxin/p/14092528.html

    实验八

    实验要求

    1.理解Linux系统中进程调度的时机,可以在内核代码中搜索schedule()函数,看都是哪里调用了schedule(),判断我们课程内容中的总结是否准确;
    2.使用gdb跟踪分析一个schedule()函数 ,验证您对Linux系统进程调度与进程切换过程的理解;推荐在实验楼Linux虚拟机环境下完成实验。
    3.特别关注并仔细分析switch_to中的汇编代码,理解进程上下文的切换机制,以及与中断上下文切换的关系;

    实验过程

    1.重新克隆一个menu,然后重新编译内核。

    2.另打开一个窗口进行gdb远程调试,配置gdb远程调试并设置断点。



    关键代码分析

    context_switch

    static inline void context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next)
    {
        arch_start_context_switch(prev);
    
        if (unlikely(!mm)) {    //如果被切换进来的进程的mm为空切换,内核线程mm为空
            next->active_mm = oldmm;  //将共享切换出去的进程的active_mm
            atomic_inc(&oldmm->mm_count);  //有一个进程共享,所有引用计数加一
            enter_lazy_tlb(oldmm, next);  //将per cpu变量cpu_tlbstate状态设为LAZY
        } else   //普通mm不为空,则调用switch_mm切换地址空间
            switch_mm(oldmm, mm, next);
        //这里切换寄存器状态和栈 
        switch_to(prev, next, prev);
    

    switch_to

    #define switch_to(prev, next, last)
    do {
        /*
         * Context-switching clobbers all registers, so we clobber
         * them explicitly, via unused output variables.
         * (EAX and EBP is not listed because EBP is saved/restored
         * explicitly for wchan access and EAX is the return value of
         * __switch_to())
         */
        unsigned long ebx, ecx, edx, esi, edi;
    
        asm volatile(
                 "pushfl
    	"  //保存当前进程flags
                 "pushl %%ebp
    	"  //当前进程堆栈基址压栈
                 "movl %%esp,%[prev_sp]
    	"  //保存ESP,将当前堆栈栈顶保存起来
                 "movl %[next_sp],%%esp
    	"  //更新ESP,将下一栈顶保存到ESP中
                         // 完成内核堆栈的切换
                 "movl $1f,%[prev_ip]
    	"    //保存当前进程的EIP
                 "pushl %[next_ip]
    	"       //将next进程起点压入堆栈,即next进程的栈顶为起点
                 __switch_canary              //next_ip一般为$1f,对于新创建的子进程是ret_from_fork      
                 "jmp __switch_to
    "    //prve进程中,设置next进程堆栈,jmp与call不同,是通过寄存器传递参数(call通过堆栈),所以ret时弹出的是之前压入栈顶的next进程起点
                 //完成EIP的切换
                 "1:	"            //next进程开始执行       
                 "popl %%ebp
    	"  //restore EBP
                 "popfl
    "         //restore flags
    
                 //输出量
                 : [prev_sp] "=m" (prev->thread.sp),   //保存当前进程的esp
                   [prev_ip] "=m" (prev->thread.ip),     //保存当前进仓的eip
                   "=a" (last),
    
                   //要破坏的寄存器
                   "=b" (ebx), "=c" (ecx), "=d" (edx),
                   "=S" (esi), "=D" (edi)
    
                   __switch_canary_oparam
    
                  //输入量
                 : [next_sp]  "m" (next->thread.sp),   //next进程的内核堆栈栈顶地址,即esp
                   [next_ip]  "m" (next->thread.ip),     //next进程的eip
    
                   // regparm parameters for __switch_to(): 
                   [prev]     "a" (prev),
                   [next]     "d" (next)
    
                   __switch_canary_iparam
    
                 : //重新加载段寄存器
                "memory");
    } while (0)
    

    总结

    1.schedule函数:

    Linux内核通过schedule函数实现进程调度,schedule函数在运行队列中找到一个进程,把CPU分配给它。所以调用schedule函数的时候就是进程调度的时机。

    2.进程调度时机:

    用户进程通过特定的系统调用主动让出CPU。
    中断处理程序在内核返回用户态时进行调度。
    内核线程主动调用schedule函数让出CPU。
    中断处理程序主动调用schedule函数让出CPU,涵盖第一和第二种情况。

    3.进程切换

    4.Linux系统的运行过程

    Linux系统的一般执行过程:正在运行的用户态进程X切换到用户态进程Y的过程:
    1.正在运行的用户态进程X;
    2.发生中断(包括异常,系统调用等),硬件完成以下动作:
    save cs:eip/esp/eflags:当前CPU上下文压入用户态进程X的内核堆栈;
    load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack)
    3.SAVE_ALL,保存现场
    4.中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换;
    5.标号1,之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行);
    6.restore_all,恢复现场;
    7.iret-pop cs:eip/ss:esp/eflags,从Y进程的内核堆栈中弹出(2)中硬件完成的压栈内容;
    8.继续运行用户态进程Y。

  • 相关阅读:
    Eclipse安装Hadoop插件
    (转)Ubuntu14.0.4中hadoop2.4.0伪分布模式配置
    Hadoop--DataNode无法启动
    启动与关闭hadoop
    hadoop中执行命令时发生错误
    strings命令
    Deriving data from ElasticSearch Engine
    elasticsearch data importing
    reading words in your computer and changing to female voice, linux festival text2wave saving wav files
    DDNS client on a Linux machine
  • 原文地址:https://www.cnblogs.com/hyuxin/p/14092528.html
Copyright © 2011-2022 走看看