Linux系统之Uboot、Kernel、Busybox思考之二

news/2024/4/27 0:37:17/文章来源:https://blog.csdn.net/wwwyue1985/article/details/129150192

目录

三 内核的运行

1

2

3

4


三 内核的运行

1

内核启动后,控制权交给用户空间程序,操作系统进入怠速状态。这个时候就可以加载新的业务应用来执行。

当然内核也提供了多种途径,来保障新业务运行所需环境的构建。比如,如果有专有驱动,可以在业务应用构建过程中动态加载。

动态库的环境变量可以进行修改。也允许一些依赖库可以早于C库加载。

系统正常运行后,内存中存在用户进程,内核进程,空闲进程及中断这几种上下文。当前CPU执行的任何一行代码都可以归类到上述某种上下文中。

2

到目前这里,我们一直混用进程和线程的概念,特别是在讨论到有关内核部分时。关于这两个概念的差异,个人理解如下:

为什么讲内核线程、内核进程和应用进程?分清楚进程和线程的定义,这一点在内核也是不例外的,有助于进一步理清上述几个概念。首先,线程之间是共享全局信息的,进程之间通过虚拟地址空间反而进行了隔离。所以,我们在应用层讲应用进程,因为各个应用之间是虚拟隔离的,这一点很好理解。提到应用线程,肯定是某个应用进程内的线程,这一点也是没有异议的。此时的沟通语境是一致的。

其次,为啥又在内核时,多会讲内核线程,因为内核线程是没有像应用那样的地址映射的。内核线程之间共享内核地址空间,映射一般是单一的对应映射。不像应用进程,每个有其独立的进程页表,用于获取内存页映射信息,在不连续的物理页上构建连续的虚拟地址空间。可以将内核看作一个大的进程,这样内核里共享内核全局信息的各个线程自然就被称作内核线程了。这样来看,内核线程提法也算是比较准确的。

那为啥又会提到内核进程呢?个人觉得这主要是与应用进程对应。一般讲,内核实现进程调度,进程管理,这里应该是与应用进程对应的。应用进程通过do_fork系统调用进入内核空间,进行调度时,跟内核其他线程是类似的。这时候为了方便理解,我们也可以将内核线程叫做内核进程。

实际上,一个应用进程对应到内核的是一个或多个内核线程。如果是单线程的应用进程,则是一个,否则是多个。这里针对pthread库创建线程的情况,下同。进一步的,应用进程对应的各个线程可以对应到内核线程,但是如何又做到共享应用进程全局信息的呢,个人猜测这些线程通过pthread或者其他库创建时,

虽然都是一个一个的内核线程,但是同属于一个应用进程的各个线程应该是共享了应用的地址空间映射,从而感觉是单进程多线程模式。实际上,通过不同的系统调用及参数,内核在创建线程时,会进行特殊处理。比如,可以指定是否共享虚拟内存空间,是否共享文件、设备句柄等。通过这种方式,实现了线程的要求。

Linux线程在内核看跟普通进程没有区别。所有用户空间进程的创建都是通过fork调用完成。fork调用通过clone系统调用创建进程。clone最终调用内核的do_fork完成进程的创建。

在clone系统调用中,可以提供诸多参数,这些参数就有是否共享父进程的文件系统、虚拟空间、打开的文件等等。可见,线程的创建是通过控制这些参数完成的。

最终线程在内核跟其他进程一样,也是task的实例,只不过他们跟父进程共享虚拟空间,我们才可以在用户空间实现全局变量在线程间的共享。

3

上下文切换

前面提到,内存中的任何一条指令,或者说CPU执行的任何一行代码,都是可以归类到某个上下文中的。不管这个上下文是用户进程、内核线程还是中断环境。

所谓的上下文切换,就是CPU在上述几种环境中切换。其实对CPU来讲,比如将自己想想成CPU,它是不知道当前是什么上下文的,CPU看到的只是内存中的指令序列。

上下文是用户人为设定的,方便系统资源的使用和管理。

有不同的上下文,就涉及到上下文切换。比如,从用户进程切换到内核空间,此时的内核空间可以看作还是用户进程上下文。从内核空间切换到内核中断,从内核中断切换到软中断,从软中断切换到内核线程,等等。不同的切换情况,做不同的动作,这在后面会介绍。

有上下文切换,就涉及到切换时机。切换时机包括两类,一种是主动切换,一种是被动切换。主动切换是指通过执行某些代码,主动让出CPU。

比如,通过执行触发睡眠的函数,等待IO的函数等,资源不满足的情况下,内核都会将当前进程放入等待队列,然后调度新的进程,此时发生主动切换。

如果进程在执行过程中发生了中断或新的更高优先级的进程资源准备好了,内核会将当前运行进程挂起,然后调度执行新的进程或处理中断,此时发生被动切换。

不管是主动切换还是被动切换,不管是从用户进程切换到内核线程还是从内核中断切换到其他环境,发生切换时,需要做哪些动作,这是切换的实质。

要了解切换做哪些动作,就需要知道与上下文相关的东西。上下文相当于一个执行实体的环境,主要包括了三个大的部分:

首先是CPU寄存器。因为切换后还要切换回来,所以当前CPU执行的环境是需要保存的,否则切换回来不知道下一条指令在哪里。

其次是内存中任务结构体。这是进程在内核中的表示。通过结构体,可以保存进程打开的系统资源。比如文件、网络等。这些也是需要保存好的,每个进程都不一样。

最后是与内存相关的。一是进程的虚拟内存映射表,特别是目录表,需要保存和恢复;二是cache。进程切换,可能会引发大量cache miss,目前硬件提供专门的模块,支持减少cache miss的情况。

4

优先级与调度策略

  nice

  rt

  120

  20

  -20 --- 19

  bonus -5

存在疑问,调度器是存在多个?普通进程和实时进程分别调度是什么意思?nice对应到调度方式(创建线程时)跟调度器的关系?调度时机的问题。

内核通过调用schedule接口进行调度。

站在不同角度,如果你是操作系统调度器的设计者,会如何设计调度器,会考虑哪些因素,结合这些理解Linux调度器设计。

实际场景中,几乎都是需要并行执行多个任务。

实际硬件上,单核就不用说了,即使是多核CPU,比如SMP,核心数量跟需要并行运行的任务相比,也是不在一个数量级的。

操作系统中,任务都会抽象为进程或者线程,而且系统中的进程往往会有上百甚至几百个,但是CPU的资源是有限的,时间是单调流失的,如何让这些进程在宏观上看起来是并行的,这就是操作系统调度要做的工作

不单是要任务看起来并行运行,而且不同的任务对执行有着不同的要求。

交互性任务,系统在事件满足的时候,要能够立即得到CPU进行处理,否则用户就会有延迟滞后的感觉,比如鼠标操作。

计算性任务需要得到更多的CPU执行时间,以便能够完成计算任务。这类任务对响应的及时性要求没有交互性任务敏感。

当然,还有一些任务,可能是交互和计算并重的。比如视频编辑软件,操作的流畅性,既需要交互得到及时响应,也需要进行大量CPU计算来反馈结果。二者相互影响。

操作系统调度的理想效果就是让需要交互的任务能够在需要响应时尽快的运行,让需要计算的任务能够获得更多的运行时间,让二者并重的任务能够在响应的及时性和计算资源获取上得到很好的平衡。

对操作系统来讲,它看到的是成百的需要调度的任务,有限的可运行的CPU核心,以及时限的敏感要求。

操作系统调度器需要在有限的时间内将可运行的任务调度,并让每个任务有一定的运行时间。

这里,时间是一个硬性要求,如果一个任务每间隔好几秒才会调度运行一次,那么在用户层最可能的感受就是系统快卡死了。所以,一个任务的最大调度间隔是多少才不会影响用户使用,这没有一个标准答案,调度器面对的场景是复杂的。但是通常来讲,感觉上这个值不能够大于1秒。

Linux内核中,有一个最小运行时间参考,是0.75ms,时钟tick是100或者1000,对应10ms或者1ms,这些都是可参考的数值。

当然,这里的时间是受到任务数量的影响的,不能脱离实际。如果系统中有几千个需要调度运行的任务,即使按照0.75来计算,也难以在1秒内调度一遍。当然,这种情况有点极端。

前面提到,实际场景中,任务是有其特点的,结合任务的特点,调度器需要做到:

等待事件的任务,在事件到达后,能够尽快的调度到并运行。

等待运行的任务,能够合理的分配给相应的CPU,选择CPU的原则有CPU的繁忙程度和CACHE匹配情况

所有等待运行的任务,能够在特定的时间内调度运行一次。避免长时间处于饥饿状态

任务要有区别,这种区别会影响到调度器对任务的选择。简单来讲,就是任务要有优先级差异。高优先级先调度,多运行。

任务运行时间要有限制,无论是主动放弃还是被动抢占,所以任务要有运行时间记录

将自己想象成上帝,站在全局角度,俯视下界,可以看到一些CPU和一堆要运行的有各种各样特点的任务。此时,你的思考、选择及这其中对平衡的把握,就是调度器要实现、要做、要完成的事。

在Linux中,相关概念如下:

系统中所有的任务可以分为两大类,实时任务和普通任务

每个CPU有运行队列和等待队列

队列采用红黑树进行插入删除

调度的时机有主动调度和被动调度。主动调度是当前任务放弃执行或者通过中断和系统调用返回用户空间时,执行schedule进行主动调度

被动调度有时钟中断处理触发的调度,也有任务因为等待特定事件而放弃执行导致调度,还有任务等待的事件发生后触发的调度。(最后这一种待确定。根据资料,Linux在唤醒队列中任务时,只是设置了调度标识,而非立即介入调度)。

调度时,先检查当前是否存在实时任务,如果没有,则使用cfs调度器对普通任务进行O(1)复杂度的公平调度。否则,优先调度实时任务。实时任务分两种,FIFO和RR,FIFO按先到先调度,RR按轮流调度

按照内核的设计,似乎是定义好了抽象的调度接口,系统各个地方需要时会调用这些接口。但是接口的具体实现,可以不同。就是可以根据需要添加不同规则和策略的调度器。

关于优先级,实时进程优先级1-99,普通进程100-139,具体受nice影响。nice范围-20到19。内核中对不同nice的进程,分配不同的权重。

上述优先级为静态优先级,任务运行过程中,会对优先级进行计算,生成动态优先级,最终依据动态优先级进行调度。

进程的时间片转换为虚拟运行时间,该时间为物理时间与权重的比重乘积。虚拟时间越小,越先调度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_72358.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Crafting interpreters 中文翻译,持续修正

本书在线地址 http://craftinginterpreters.com/ 感谢作者 作者用近 4 年的时间持续创作和改进本书,并把其 Web 版本公开在网上。这本纸质书于今年 7 月出版,立刻在 Hacker News 等网络媒介上引起关注和讨论。 书中作者首先定义了一个动态类型的语言 …

棋牌类游戏测试用例怎么写?我敢打赌你绝对不知道

目录 一.登陆 二.大厅 三.小游戏 四.银行功能 五.其他按钮 总结感谢每一个认真阅读我文章的人!!! 重点:配套学习资料和视频教学 一.登陆 1&#xff0e…

使用拦截器实现登录状态检测(以及在注册拦截器类时要使用ioc中的拦截器类)

拦截器 preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在请求处理之前被调用。该方法在 Interceptor 类中最先执行,用来进行一些前置初始化操作或是对当前请求做预处理,也可以进行一些判断来决定请求是否…

【MyBatis】源码学习 04 - 从 MapperMethod 简单分析一条 SQL 的映射操作流程

文章目录前言参考目录学习笔记1、测试代码说明2、binding 包的主要功能3、获取 Mapper 接口实例过程4、SQL 语句执行流程4.1、方法调用器4.2、MapperMethod 绑定方法4.2.1、SqlCommand4.2.2、MethodSignature4.3、MapperMethod#execute前言 本文内容对应的是书本第 13 章的内容…

循环、函数、对象——js基础练习

目录 一、循环练习 1.1 取款机案例 1.2 九九乘法表 1.3 根据数据生成柱形图 1.4 冒泡排序 1.6综合大练习 二、函数 2.1 转换时间案例 三、对象 1. 遍历数组对象 2. 猜数字游戏 3. 生成随机颜色 4. 学成在线页面渲染案例 一、循环练习 1.1 取款机案例 // 准备一个…

电商项目之Feign与Dubbo技术选型

文章目录1 问题背景2 前言3 思路4 Feign与Dubbo的区别5 总结6 真实案例1 问题背景 电商项目,B端以consul作为注册中心。重构了一个营销服务,以Nacos作为注册中心。B端需要调用营销服务。关于远程调用框架,营销服务用了Dubbo,而B端…

黑马程序员-Linux网络编程-01

目录 课程链接 协议 分层模型 网络传输数据封装流程 以太网帧和ARP请求 IP协议 TCP协议 BS与CS模型对比 套接字 网络字节序 IP地址转换函数 sockaddr地址结构 socket模型创建流程 socket()和bind() listen()和accept()​ 课程链接 03-协议_哔哩哔哩_bilibili 协…

java并发笔记

文章目录HashMapput方法resize方法ConcurrentHashMapput方法initTable方法sizectl代表什么:扩容计数器ConcurrentHashMap的读操作会阻塞嘛AQS唤醒线程时,AQS为什么从后往前遍历?AQS为什么要有一个虚拟的head节点AQS为什么用双向链表&#xff…

万字C语言学习笔记,带你学C带你飞(四)

文章目录单链表typedef1、基础typedef2、进阶typedef共用体枚举类型1、声明枚举类型2、定义枚举变量位域位操作文件的写入与写出C语言学习笔记,记录所学,便于复习。 由于篇幅过大,考虑到观感,准备分多篇记录。学习视频链接&#x…

Vue3.x使用Echarts绘制世界地图并进行定点

Vue3.x使用Echarts绘制世界地图并进行定点 一、需求 绘制世界地图并根据返回经纬度数据进行定点将定点数据展示在世界地图内 二、解决 绘制世界地图,利用Echarts图表组件时间,需要世界地图Geojson数据的可以在资源中下载世界地图Geojson数据-Javascr…

2022FALL嵌入式大纲

Jamslade 部分内容有遗漏,可结合 超文本 2022FALL《嵌入式系统原理》期末复习笔记 一起观看 文章目录嵌入式系统片上系统实时系统硬实时系统软实时系统伪指令DMA传输波特率单/半双/全双工通信;对齐/非对齐访问地址译码代码临界区RISCBIOSUARTSPII2CWDTRO…

2.5|shell简介|Linux支持的网络协议|Linux的网络服务

shell简介shell是一种具备特殊功能的程序,它是介于使用者和Unix/Linux操作系统内核间的一个接口。操作计算机需要通过命令(command)或是程序(program);程序需要编译器(compiler)将程…

东南大学研究生英语18-19秋试卷解析

写在前面 作者:夏日 博客地址:https://blog.csdn.net/zss192 本文为东南大学研究生英语上学期18-19年期末试卷解析,答案来源于 ChatGPT International Conference 单选题 1.A presenter is supposed to do the following in an introdu…

【数据结构趣味多】八大排序

目录 1.直接插入排序 基本思想 代码实现: 直接插入排序的特性总结: 2.希尔排序 基本思想 代码实现 (递归实现) 希尔排序的特性总结 3.直接选择排序 基本思想 代码实现: 直接选择排序的特性总结 4.堆排序 …

Springboot 全局异常处理类

全局异常处理 在开发过程中,不管是Dao、Servie、Controller,层都有可能发生异常,对于异常处理,通常是try-catch或者直接throw,这会让try-catch的代码在代码中任意出现,系统的代码耦合度高&…

深入Spring底层透析bean生命周期及循环引用的醍醐灌顶篇

目录前言一.Bean的生命周期1.1 Bean的实例化阶段1.2 Bean的初始化阶段(重点)1.3 Bean的完成阶段二.循环引用问题(面试常问题)三.Spring的三级缓存(重点来了)四.完整的Spring IoC整体总结前言 本篇是接着bean的创建基本…

2023/02/21 事件循环-eventloop 宏任务 微任务 讲解

1 JS是单线程 js是单线程的。也就是说,同一个时间只能做一件事。作为浏览器脚本语言,与它的用途有关。JavaScript的主要用途是和用户互动,以及操作DOM,这决定了它只能是单线程。 js是单线程的。也就是说,同一个时间只…

非常优秀的网站设计案例,设计师必备

厚积才能薄发,一个优秀的设计师的天性一定是想要获得更多网站设计灵感,擅于为新项目寻找创意切入点、搜索设计参考资源、最新的设计趋势。今天为大家带来了一组免费可商用的网站设计案例,通过这些网站设计案例,你可以获得&#xf…

CF707C Pythagorean Triples 题解

CF707C Pythagorean Triples 题解题目链接字面描述题面翻译题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1样例 #2样例输入 #2样例输出 #2样例 #3样例输入 #3样例输出 #3样例 #4样例输入 #4样例输出 #4样例 #5样例输入 #5样例输出 #5提示思路代码实现题目 链接 http…

华为OD机试 - 最短耗时(C++) | 附带编码思路 【2023】

刷算法题之前必看 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12199283.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 华为OD机试题…