进程切换,又称为任务切换、上下文切换、或者任务调度。本文就研究Linux内核的进程切换。我们首先理解几个概念。
因此当前linux的调度程序由两个调度器组成:主调度器,周期性调度器(两者又统称为通用调度器(generic scheduler)或核心调度器(core scheduler))
(1)进程状态转换的时刻:进程终止、进程睡眠,这些过程会主动调用调度程序进行进程调度。 (2)当前进程时间片用完时 (3)进程从中断、异常及系统调用返回到用户态时
在操作系统运行过程中,由于CPU bound和I/O bound,进行进程的调度自然是常事。进行进程调度时,操作系统使用某些特定算法(如FIFO、SCBF、轮转法等)在进程队列中选出一个进程作为下一个运行的进程,调用schedule。进行进程调用的时机有以下几种: 中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule(); 内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行
DragonOS是一个从0开始研发内核及用户态环境的,独立自主的,面向服务器领域的开源操作系统,提供Linux兼容性。
linux的上下文切换就是进程线程的切换,也就是切换struct task_struct结构体,一个任务的上下文包括cpu的寄存器,内核栈等,由于1个cpu上的所有任务共享一套寄存器,所以在任务挂起的时候需要保存寄存器,当任务重新被调度执行的时候需要恢复寄存器。每种处理器都提供了硬件级别的上下文切换,比如x86架构下的TSS段,TSS段包括了一个任务执行的所需要的所有上下文,主要有:1.通用寄存器和段寄存器。2.标志寄存器EFLAGS,程序指针EIP,页表基地址寄存器CR3,任务寄存器和LDTR寄存器。3.I/O映射位图基地址和I/O位图信息。4.特权级0,1,2堆栈指针。5.链接到前一任务的链指针。所以上下文切换也很简单,直接用call或者jmp指令调度任务。同样ARM架构也有快速上下文切换技术。但是Linux为了适用更多的cpu架构没使用处理器相关的上下文切换技术,而是大部分通过软件实现。linux上下文切换就在schedule()函数里,很多地方都会调用这个函数。scchedule函数前面大部分代码是和调度算法相关的,比如实时任务调度算法,O(1)调度算法(2.6.22版本被CFS调度算法取代),CFS调度算法等。经过前面的代码计算后找出下一个要执行的任务,然后开始执行上下文切换。先看一段linux2.6.18版本还使用O(1)调度算法的schedule函数代码:
原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/
前面我们说过,进程的切换总是通过 shedule 函数发生的,而 schedule 函数可以是在系统调用返回、中断返回等时机被调用,也可以进程在驱动程序中主动调用
在内核中的许多地方, 如果要将CPU分配给与当前活动进程不同的另一个进程, 都会直接调用主调度器函数schedule, 从系统调用返回后, 内核也会检查当前进程是否设置了重调度标志TLF_NEDD_RESCHED
本文主要是以context_switch为起点,分析了整个进程切换过程中的基本操作和基本的代码框架,很多细节,例如tlb的操作,cache的操作,锁的操作等等会在其他专门的文档中描述。进程切换包括体系结构相关的代码和系统结构无关的代码。第二、三、四分别描述了context_switch的代码脉络,后面的章节是以ARM64为例子,讲述了具体进程地址空间的切换过程和硬件上下文的切换过程。
本系列参考: 学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春 整理而来,主要作为xv6操作系统学习的一个前置基础。
在执行sys_fork的时候,可能会引起切换,例如: 如果产生了阻塞或者时间片到期了
调度器面对的情形就是这样, 其任务是在程序之间共享CPU时间, 创造并行执行的错觉, 该任务分为两个不同的部分, 其中一个涉及调度策略, 另外一个涉及上下文切换.
lab4 会依赖 lab1、lab2 和 lab3,我们需要把做的 lab1、lab2 和 lab3 的代码填到 lab4 中缺失的位置上面。练习 0 就是一个工具的利用。这里我使用的是 Linux 下的系统已预装好的 Meld Diff Viewer 工具。和 lab3 操作流程一样,我们只需要将已经完成的 lab1、lab2 和 lab3 与待完成的 lab4 (由于 lab4 是基于 lab1、lab2、lab3 基础上完成的,所以这里只需要导入 lab3 )分别导入进来,然后点击 compare 就行了。
我是一个线程,生活在Linux帝国。一直以来辛勤工作,日子过得平平淡淡,可今天早上发生了一件事让我回想起来都后怕。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014688145/article/details/50644876
前面选择了一个合适进程作为下一个进程,接下来做重要的上下文切换动作,来保存上一个进程的“上下文”恢复下一个进程的“上下文”,主要包括进程地址空间切换和处理器状态切换。
方式一:A 项目做着做着,发现里面有一条指令 sleep,也就是要休息一下,或者在等待某个 I/O 事件。那没办法了,就要主动让出 CPU,然后可以开始做 B 项目。
IO是个耗费时间的活,如果CPU在取值执行过程中,遇到了IO指令,那么必须等当前IO执行完毕后,才能继续取出下一条指令去执行,显然这种同步等待机制,并没有充分利用CPU的性能。
在内核层面,每个进程都是由task_struct 描述的,这个结构体非常大,可以粗略看下各主要内容:
考虑到文章篇幅,在这里我只讨论普通进程,其调度算法采用的是CFS(完全公平)调度算法。 至于CFS调度算法的实现后面后专门写一篇文章,这里只要记住调度时选择一个优先级最高的任务执行
每个进程有一个执行的时间,每次时钟中断会减少一个单位的时间。如果时间用完则直接重新调度,否则进程可以继续执行。进程调度的时候,系统会选择时间最长的进程,防止有的进程得不到执行,当所有进程的时间片都消耗完毕,则重新计算时间。
虽然讲解完了内核线程的创建过程,但是似乎又少点什么,那么下面我们来看两个细节:内核线程执行处理函数和内核线程上下文切换细节:
操作系统启动就是将操作系统从磁盘读入内存,然后调用相关初始化方法,初始化形成相关数据结构,让操作系统知道硬件的模样,然后启动shell,等待用户使用。
韩传华,就职于南京大鱼半导体有限公司,主要从事linux相关系统软件开发工作,负责Soc芯片BringUp及系统软件开发,乐于分享喜欢学习,喜欢专研Linux内核源代码。
小编所在项目的客户端是比较奇怪的一个APP,大部分页面Android和iOS的客户端只提供了webview的功能,都是由H5处理业务逻辑和用户交互。H5承担了和服务端、和客户端的交互。
每一种技术的出现必然是因为某种需求。正因为人的本性是贪婪的,所以科技的创新才能日新月异。
Go语言从诞生到普及已经三年了,先行者大都是Web开发的背景,也有了一些普及型的书籍,可系统开发背景的人在学习这些书籍的时候,总有语焉不详的感觉,网上也有若干流传甚广的文章,可其中或多或少总有些与事实不符的技术描述。希望这篇文章能为比较缺少系统编程背景的Web开发人员介绍一下goroutine背后的系统知识。 1. 操作系统与运行库 2. 并发与并行 (Concurrency and Parallelism) 3. 线程的调度 4. 并发编程框架 5. goroutine 1. 操作系统与运行库 对于
Go语言从诞生到普及已经三年了,先行者大都是Web开发的背景,也有了一些普及型的书籍,可系统开发背景的人在学习这些书籍的时候,总有语焉不详的感觉,网上也有若干流传甚广的文章,可其中或多或少总有些与事实不符的技术描述。希望这篇文章能为比较缺少系统编程背景的Web开发人员介绍一下goroutine背后的系统知识。 1. 操作系统与运行库 2. 并发与并行 (Concurrency and Parallelism) 3. 线程的调度 4. 并发编程框架 5. goroutine 1. 操作系统与运行库 对
1983年,理查德·斯托曼(Richard Stallman)在MIT人工智能实验室(AI Lab)创立了GNU计划,目标是创建一个完全自由的Unix类操作系统。在这个计划中,斯托曼和其他志愿者开发了GNU工具链(GCC、GDB、GNU Make等),但操作系统内核一直没有完成。
Go语言从诞生到普及已经三年了,先行者大都是Web开发的背景,也有了一些普及型的书籍,可系统开发背景的人在学习这些书籍的时候,总有语焉不详的感觉,网上也有若干流传甚广的文章,可其中或多或少总有些与事实不符的技术描述。希望这篇文章能为比较缺少系统编程背景的Web开发人员介绍一下goroutine背后的系统知识。 1. 操作系统与运行库 2. 并发与并行 (Concurrency and Parallelism) 3. 线程的调度 4. 并发编程框架 5. goroutine 1. 操作系统与运行库 对于普通的
进程定义:所谓进程是由正文段(Text)、用户数据段(User Segment)以及系统数据段(System Segment)共同组成的一个执行环境。它代表程序的执行过程,是一个动态的实体。
本文是练习篇的最后一篇文章,虽然练习篇的文章到此就要和大家说拜拜了,但是我们的学习之路才刚刚开始。不要停下你的脚步,大步朝前走吧!比你优秀的人还在走着,我们有什么理由停下自己的脚步了,生命不止,学习亦是如此。好了,宏哥的毒鸡汤好
遇到“noSuchElement”原因是把元素放在iframe里面,根本就找不到。
在支持可抢占的系统中,一个进程的therad_info信息定义如上。其中preempt_count代表的是该进程是否可以被抢占,根据注释的说明当peermpt_count等于0的时候当前进程就可以被抢占,当小于0存在bug,当不等于0也就是大于0说明当前进程不可以被抢占。不可抢占的原因很多,比如当前进程在中断上下文中或者使用了锁(spin_lock的过程中会disable掉抢占的)。至于当前是什么原因不能被抢占,就需要看peermpt_count每个字段的含义。
alloc_proc函数(位于kern/process/proc.c中)负责分配并返回一个新的struct proc_struct结构,用于存储新建立的内核线程的管理信息。ucore需要对这个结构进行最基本的初始化,你需要完成这个初始化过程。
crash 是 Linux 内核开发中流行的调试工具。特别是它提供了强大的使用搜索命令进行内存搜索的功能。但是,它有点不方便,因为在移动每个进程的调用堆栈时没有查看局部变量的功能。 应读者要求,这篇文章,我将介绍如何从 vmcore 中提取堆栈转储并将调用堆栈上传到 Trace32。 使用命令“./crash64 vmcore vmlinux”运行崩溃实用程序。 $./crash64 vmcore vmlinux ...... please wait... (gathering kmem slab cach
当异常发生时,Linux内核给造成异常的进程发送一个信号,告知其发生了异常。比如,如果一个进程尝试除零操作,CPU会产生除法错误异常,相应的异常处理程序发送SIGFPE信号给当前进程,然后由其采取必要的步骤,恢复还是中止(如果该信号没有对应的处理程序,则中止)。
driver.switch_to.frame(通过find_element_by函数定位的frame、iframe标签对象)
现在越来越多的 Web 自动化项目都在使用 Selenium,其特点为提供丰富的 API 功能、支持多语言、多平台等。
Hi,大家好。在上一篇Helium自动化测试系列文章:介绍一下Selenium的集美:优秀的Helium,主要Helium特点、安装及通过案例展示了Helium的简洁之美。
当进程1执行陷入阻塞时,需要进行进程调度,此时有进程2和进程3都处于就绪态,问: 应该选择哪个进程进行切换?
本文是《Linux内核设计与实现》第四章的阅读笔记,代码则是摘自最新的4.6版本linux源码(github),转载请注明出处。
程序是指储存在外部存储(如硬盘)的一个可执行文件, 而进程是指处于执行期间的程序, 进程包括 代码段(text section) 和 数据段(data section), 除了代码段和数据段外, 进程一般还包含打开的文件, 要处理的信号和CPU上下文等等.
我们可以把内核想象成一个服务器,专门响应各种请求。这些请求可以是CPU上正在运行的进程发起的请求,也可以是外部的设备发起的中断请求。所以说,内核并不是串行运行,而是交错执行。既然是交错执行,就会产生竞态条件,我们可以采用同步技术消除这种竞态条件。
领取专属 10元无门槛券
手把手带您无忧上云