schedule函数进行调度时,首先选择一个新的进程来运行,然后调用context_switch进行上下文的切换,这个宏又调用switch_to进行关键上下文的切换。...next = pick_next_task(rq, prev);//进程调度算法都封装这个函数内部 context_switch(rq, prev, next);//进程上下文切换 switch_to利用了...1继续执行) restore_all //恢复现场 iret - pop cs:eip/ss:esp/eflags from kernel stack 继续运行用户态进程Y 下面是switch_to的代码...而调用switch_to时,也并不是通过普通的call来实现,而是直接jmp到switch_to。...陈政/arc001 原创作品转载请注明出处 《Linux内核分析》MOOC课程
1 前景回顾 1.1 Linux的调度器组成 2个调度器 可以用两种方法来激活调度 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测是否有必要...LINUX完全注释中的一段话 当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称 为该进程的上下文。...在LINUX中,当前进程上下文均保存在进程的任务数据结 构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。...Linux相比与其他操作系统(包括其他类 Unix 系统)有很多的优点,其中有一项就是,其上下文切换和模式切换的时间消耗非常少. 3 context_switch进程上下文切换 linux中进程调度时,...另外需要注意, 内核线程没有自身的用户空间上下文, 其task_struct->mm为NULL, 参见Linux内核线程kernel thread详解–Linux进程的管理与调度(十), 从当前进程”借来
罗军 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 进程调度的时机 (1)进程状态转换的时刻...(3)SAVE_ALL //保存现场 (4)中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换 (5) 标号1之后开始运行用户态进程Y(这里...switch_to代码 switch_to是通过内联汇编操作的,在调试过程中无法进入,只能进入__switch_to函数。...(断点无法断下)、__switch_to 运行后单步跟踪到schedule函数,发现实际调用的是__schedule函数,接下来完成进程切换的操作: ?...switch_to函数: ? __switch_to函数: ?
本文就研究Linux内核的进程切换。我们首先理解几个概念。 1.1 硬件上下文 我们知道每个进程都有自己的地址空间,但是所有的进程却共享CPU寄存器。...在Linux中,进程的硬件上下文一部分存储在进程描述符中,而其它部分存储在内核态的栈中。 在下面的描述中,我们假设,prev指向旧进程,而next指向新进程。...尽管Linux不使用硬件上下文切换,但还是给每个不同CPU建立一个TSS。...在Linux的设计中,每个CPU就只有一个TSS,所以,Busy位总是设为1。换句话说,Linux中Type域一般为11。...显然不能保存在TSS中,因为Linux为每个CPU就建立了一个TSS,而不是为每个进程建立TSS。
__sched前缀的声明, 在include/linux/sched.h, L416, 如下所示 /* Attach to any functions which should be ignored in...内核抢占是Linux 2.6以后引入的一个重要的概念 我们说:如果进程正执行内核函数时,即它在内核态运行时,允许发生内核切换(被替换的进程是正执行内核函数的进程),这个内核就是抢占的。...加快经常性事件, 是程序开发中一个优化的准则, 那么linux系统中最普遍的进程是什么呢?...1.4.4 switch_to切换进程堆栈和寄存器 执行环境的切换是在switch_to()中完成的, switch_to完成最终的进程切换,它保存原进程的所有寄存器信息,恢复新进程的所有寄存器信息,并执行新的进程...检查指定进程need_resched标志 include/linux/sched.h, L2931 // http://lxr.free-electrons.com/source/include/linux
switch_to是一个有魔力的符号,和一般的调用函数不同,当A进程在CPUa调用它切换到B进程的时候,switch_to一去不回,直到在某个cpu上(我们称之CPUx)完成从X进程(就是last进程)...到A进程切换的时候,switch_to返回到A进程的现场。...switch_to完成了具体prev到next进程的切换,当switch_to返回的时候,说明A进程再次被调度执行了。 三、switch_to为什么需要三个参数呢?...\ ((last) = __switch_to((prev), (next))); \ } while (0) 一个switch_to将代码分成两段: AAA...谁知道呢(在A进程调用switch_to 的时候是不知道的)?在A进程调用switch_to之后,cpu就执行B进程了,后续B进程切到哪个进程呢?随后又经历了怎样的进程切换过程呢?
前言的前面 DragonOS是一个从0开始研发内核及用户态环境的,独立自主的,面向服务器领域的开源操作系统,提供Linux兼容性。...,当__switch_to函数返回时,处理器将会弹出63行压入的“下一个进程的RIP”,这样就完成了进程切换。...r=d4f3de93#9 注意,我为了避免歧义,在这里把原本的switch_proc()宏,改名为switch_to().在下文中,将用switch_to来代指前文的switch_proc宏。...BUG的原因之二:switch_to宏的内联汇编,是未定义行为的代码 我重新思考了很久,我坚信问题一定存在于switch_to和__switch_to这两个地方。...我盯着switch_to()宏的代码看了很久,发现它就是有点不对劲!
linux的上下文切换就是进程线程的切换,也就是切换struct task_struct结构体,一个任务的上下文包括cpu的寄存器,内核栈等,由于1个cpu上的所有任务共享一套寄存器,所以在任务挂起的时候需要保存寄存器...但是Linux为了适用更多的cpu架构没使用处理器相关的上下文切换技术,而是大部分通过软件实现。linux上下文切换就在schedule()函数里,很多地方都会调用这个函数。...先看一段linux2.6.18版本还使用O(1)调度算法的schedule函数代码: /* * schedule() is the main scheduler function. */ asmlinkage...看switch_to宏。...然后切换到next内核栈,至此prev进程就被挂起来了,把next上次被挂起的地址压栈,调用__switch_to函数,__switch_to函数返回的时候会直接跳到标号1或者ret_from_fork
进行进程切换,switch_to 返回后,进程已经切换完毕 最后调用 finish_task_switch 对上一个进程做一些清理工作 下面我们来看 switch_to 做了什么,它其实是一个宏定义,...如下: switch_to(prev, next, prev); #define switch_to(prev, next, last) \ do { \ ((last)...进程切换不是只是从进程A切换到进程B吗,为什么在 switch_to 中是三个进程: switch_to(prev, next, prev); #define switch_to(prev, next...{ \ ((last) = __switch_to((prev), (next))); \ } while (0) 那么 switch_to 是怎么实现的呢?...你可以注意到,last 是通过 __switch_to 的函数返回值获取的 以进程C切换到进程A为例,进程C将自己的进程描述符地址放到寄存器中,然后切换到进程A,进程A得到 __switch_to 返回值
()函数 ,验证对Linux系统进程调度与进程切换过程的理解 十、分析switch_to中的汇编代码,理解进程上下文的切换机制,以及与中断上下文切换的关系 总结 原创作品转载请注明出处 + https:...它定义在linux-3.18.6/include/linux/sched.h文件中。 1....建议使用内核Linux-3.18.6来进行实验,这里用到的 5.0.1 内核有些函数名可能发生了变化。...$ b __switch_to 由以上跟踪结果可以得知,在进行进程间的切换时,各处理函数的调用顺序如下:pick_next_task -> context_switch -> __switch_to...十、分析switch_to中的汇编代码,理解进程上下文的切换机制,以及与中断上下文切换的关系 函数的调用关系: schedule() --> context_switch() --> switch_to
操作系统进程的实现---中---05 内核级线程实现 核心级线程的两套栈,核心是内核栈… 整个故事要从进入内核开始——某个中断开始… 切换五段论中的中断入口和中断出口 switch_to难点分析 另一个故事...下面先来看看sys_fork执行完后的代码 将当前线程PCB赋值给eax 判断PCB的状态是否为0,在linux 0.11中,0是就绪状态,而非0是阻塞状态 如果调用了相关sys_read和...---- 再来看看执行调度的具体过程,即_schedule函数执行: 通过相关调度算法,找出切换到哪个线程继续执行 switch_to完成具体切换,主要是完成对内存级线程PCB的切换 ---- switch_to...难点分析 参考: Linux0.11内核–进程的调度schedule和switch_to解析 任务状态段TSS及TSS描述符、局部描述符表LDT及LDT描述符 Linux 0.11用tss切换,但也可以...0.11中switch_to的完整源码实现 switch_to() (sched.h 第173行) /**********************************************
这里我使用的是 Linux 下的系统已预装好的 Meld Diff Viewer 工具。...再分析 switch_to 函数 * 实现思路: switch_to 函数主要完成的是进程的上下文切换,先保存当前寄存器的值,然后再将下一进程的上下文信息保存到对于寄存器中。 1....由 switch_to 函数完成具体的两个线程的执行现场切换,即切换各个寄存器,当 switch_to 函数执行完 “ret” 指令后,就切换到 initproc 执行了。...//en.wikipedia.org/wiki/SLOB https://lwn.net/Articles/157944/ https://www.ibm.com/developerworks/cn/linux.../l-linux-slab-allocator/
下面我们先来看看任务切换的实现流程: 我们可以在程序中调用switch_to函数,手动完成任务的切换,由于任务切换十分频繁,所以这里使用汇编来实现switch_to函数: # void switch_to...switch_to(struct context *next); # 其中函数有一个context指针作为参数,而实际上由a0作为参数寄存器,存放该context指针的值 .globl switch_to....align 4 switch_to: # 交换mscratch和t6寄存器的值--t6指向进程的Context上下文地址 csrrw t6, mscratch, t6 # swap t6...and mscratch # 判断switch_to函数是否是首次调用(t6==0),如果是则跳到标签1处执行 beqz t6, 1f # Note: the first time switch_to...ret call switch_to将要切换的上下文Context地址作为参数传入,由a0参数寄存器保存 switch_to函数首先判断是否为首次调用switch_to函数,如果是,则直接进行上下文恢复操作
(next); } 在协作式任务切换一节中的switch_to函数实现里面,我们采用的是ret指令进行的函数返回,ret指令执行后,会跳回到ret指令到ra寄存器保存的地址处继续执行。...而在抢占式多任务的实现中,我们的switch_to函数是在中断处理程序中执行的,所以函数返回靠的应该是mret指令,而非ret指令: 而对于mret指令而言,我们需要知道: 因此,和...函数 switch_to(next); } 因为没有采用中断调用,因此为了让switch_to函数能够像被中断调用那样执行,我们也需要提前将任务在上下文中间中的mepc寄存器值设置好才可以。...但是本节抢占式多任务的实现中,我们已经改变了switch_to函数的工作逻辑,改为mret配合mepc实现任务切换执行。...; //return_pc += 4; } return return_pc; } switch_to函数实现复用抢占式多任务更改后的版本。
目标代码如下(linux/init/main.c): void main(void){ ..........目标代码如下(linux/init/main.c): void main(void){ ..........switch_to(next); } ? 进入调度函数后,先忽略前述的某些优先级调度算法,直接转入switch_to函数,你会发现它是通过建立映象来完成内核栈的切换的。...而内核栈切换是进程调度的核心的核心,switch_to代码的工作原理是通过TR寄存器来找到当前的tss段,当寄存器存放的内容发生改变时,便会导致TR指向的tss的内容写入CPU的所有寄存器当中,而将原来的寄存器的内容保存在原来的...switch_to(n)一旦完成切换,内核栈的内容便是子进程的内容了。
CFS调度器 linux-2.6~至今 4 Linux的调度器设计 4 Linux的调度器设计 2个调度器 可以用两种方法来激活调度 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制...这包括保存、恢复栈信息和寄存器信息 switch_to切换处理器寄存器的呢内容和内核栈(虚拟地址空间的用户部分已经通过switch_mm变更, 其中也包括了用户状态下的栈, 因此switch_to不需要变更用户栈...为什么switch_to需要3个参数 在新进程被选中执行时, 内核恢复到进程被切换出去的点继续执行, 此时内核只知道谁之前将新进程抢占了, 但是却不知道新进程再次执行是抢占了谁, 因此底层的进程切换机制必须将此前执行的进程...因此使用了一个3个参数, 但是逻辑效果是相同的, 仿佛是switch_to是带有两个参数的函数, 而且返回了一个指向此前运行的进程的指针. switch_to(prev, next, last); 即...prev = last = switch_to(prev, next); 其中返回的prev值并不是做参数的prev值, 而是prev被再次调度的时候抢占掉的那个进程last. 4.8 处理进程优先级
switch_to(prev, next, prev); barrier(); return finish_task_switch(prev); } switch_to #define switch_to...rt: RR 或 FIFO, 具体策略由 task_struct->policy 指定 - fair: 普通进程调度 - idle: 空闲进程调度 - 普通进程的 fair 完全公平调度算法 CFS(Linux...idle_sched_class 就是空闲进程的调度策略 一个实时进程队列 rt_rq 和一个 CFS 运行队列 cfs_rq 这里给大家分享几个文章,大家对背后的机制明白后,这些代码就很好理解了,这些文章涉及linux...://www.wowotech.net/process_management/scheduler-history.html https://www.ibm.com/developerworks/cn/linux
下面给出代码: context_switch ->(last) = __switch_to((prev), (next)) -> fpsimd_thread_switch(next) //浮点寄存器切换...5.2 关于__switch_to的参数和返回值 switch_to(prev, next, prev) -> ((last) = __switch_to((prev), (next)))...总结 主调度器可以说Linux内核进程管理中的核心组件,进程管理的其他部分如抢占、唤醒、睡眠等都是围绕它来运作。
sleep系统调用 我是一个线程,生活在Linux帝国。一直以来辛勤工作,日子过得平平淡淡,可今天早上发生了一件事让我回想起来都后怕。...小伙子,回来啦,走,带你们去context_switch()” 进入这个context_switch()之后,长者又带着我又做了一些准备工作,比如把当前的进程地址空间换成了小T的,最终我们来到了一个叫switch_to...告别了长者,我和小T踏上了这神秘的switch_to,跟随着一步一步的指令,我把自己线程上下文的寄存器都保存到了我的内核栈上面,然后将栈指针指向了小T的内核栈,最后把小T保存在他内核栈的指令地址加载进指令寄存器...在小H的带领下,我们又来到了那个叫switch_to地方,只不过这一次我的角色变了。 小H一顿和我之前一样的操作,把执行流程交给了我。
本篇介绍 本篇介绍下Linux 中进程管理相关的内容,包括进程状态,切换等。...接下来看下switch_to方法: /* * For newly created kernel threads switch_to() will return to * ret_from_kernel_thread...context_switch在执行完switch_to后还有一段代码,是会被谁来执行呢?...就执行进程B的指令了,那switch_to后的代码啥时候会被执行呢?...多核调度 SMP结构的多核处理器比较常见,结构如下: image.png linux使用sched_domain数据结构描述调度层级,使用sched_group描述调度组,调度组是负载均衡调度的最小单位
领取专属 10元无门槛券
手把手带您无忧上云