Linux进程:Linux切换机制主流程 Article z

2026年9月购机黄金窗口:避开首发陷阱,锁定三年持有最优解 智能手机作为典型长周期数字资产,其真实价值不仅取决于参数配置,更由系统更新支持周期、硬件老化曲线、渠道价格节奏与售后确定性共同决定。在安卓/iOS/HarmonyOS多生态并存的当下,‘发布时间’已取代‘发布型号’成为影响三年使用体验的核心变量——晚买并非落伍,而是为避开早期品控风险、等待固件成熟、捕获清仓价差、锁定完整系统支持期。尤其当厂商普遍采用LPDDR5X内存带宽衰减、VC均热板空腔率超标、AI影像算法透支隐私等隐性设计妥协时,理性决策必须从‘参数对比’转向‘持有成本建模’。本文聚焦2026年9月这 阅读详情

Linux切换并没有使用X86CPU的切换方法,Linux切换的实质就是cr3切换(内存空间切换,在switch_mm函数中)+ 寄存器切换(包括EIP,ESP等,均在switch_to函数中)。这里我们讲述下switch_to主流程:
  • 在switch_mm函数中将new_task->pgd设置到cr3寄存器中,实现页表切换,由于每个进程 3-4G的页表映射机制完全一样(从内核页表中直接复制过来的),故这里虽然切换了pgd,但是并无影响,只是在任务回到用户空 间中时,才会发生变化,因为每个任务在0-3G中的页表映射都是各自独立的;[注意]因为cr3指向的是"1st level"页表, 次级页表(2dn level)本身的address是固定不变的(内容可变),所以,内核空间所对应的一级页表内容是不变的. 在copy_mm()->dup_mm()时进行了copy.
  • 压入esi edi ebp到cur_task堆栈中;
  • 将esp寄存器中的值保存到cur_task.task_struct.thread.esp中,也就是将cur_task切换时的堆栈指针保存起来;
  • 将 new_task.task_struct.thread.esp中的值设置到esp寄存器中,这里的 new_task.task_struct.thread.esp中的值就是new_task上一次被换出时的堆栈指针,现在被恢复了,2和3结合实现了 从cur_task到new_task的堆栈切换;
  • 将1f地址设置到cur_task.task_struct.thread.eip中,当下次cur_task恢复运行时,将会从1f处开始运行,下面阐述了这种原理;
  • 将 new_task.task_struct.thread.eip压入到new_task的堆栈中,这里 new_task.task_struct.thread.eip的值就是1f,因为从4中可知,new_task上一次被换出时,其也是和现在的 cur_task类似,1f地址被设置到new_task.task_struct.thread.eip中;
  • 随后CPU跳转到 __switch_to函数(注意,在__switch_to中,做了一件非常重要的事情就是让 init_tss.esp0=new_task.task_struct.esp0,原因见【C.Linux进程:Linux进程管理和X86进程管理的 结合】一文)中开始执行,注意这里使用的是jmp,不是call,call会pusheip,而jmp不会,由于__switch_to是函数,当CPU 执行完该函数后,最后一条指令必然为iret,该指令会popeip,从5中可以知道,此时new_task堆栈中的镜像为[......., esi,edi,ebp,eip(&1f)],故popeip将值eip(&1f)设置到eip寄存器中,这样当iret执行完毕 后,CPU将从eip处继续执行,也就是从1f处继续执行;;
  • 此时已经在new_task的执行环境中了,pop ebp, pop edi, popesi,回到schedule函数中,当返回用户空间中时,由于new_task用户空间的eip,ss,esp等均被从new_task的堆栈中 弹出到对应寄存器中,从而new_task得以顺利执行;

switch_to中cur_task寄存器保存、new_task寄存器恢复的几个问题:
  • GCC在编译该段代码时,会注意到EAX,EBX,EDX在这里被使用,因此此处无需要显示的用汇编语句来保存这三个寄存器,GCC在编译时会自动考虑添加对这些寄存器的保护;
  • 由于在内核中所有的内核段寄存器均为统一的,因此这里无需保存ES,CS,SS,DS,FS,GS;
  • CR3(Linux中没有使用LDT)已经在前面的switch_mm处理了;
  • 由于Linux没使用TSS-previous task link field,其切换完全采用软件处理切换,故这里无需考虑TSS-previous task link field;
  • 指令EIP会保存在task.thread.eip中,ESP会保存在task.thread.esp中,EBP,ESI,EDI会用显示指令入栈保存;
  • 对于Linux而言,其仅仅使用到了CPU的4级机制中的0和3两级,使用方法如下:
    当进程正运行在用户空间时,如果此时来了个中断,CPU将会执行:从TR->GDTR[i ]->TSS中取出当前的SS0:ESP0,从IDTR->IDT[i ]中取出执行代码CS:IP,将当前所有寄存器压到SS0:ESP0堆栈中,包括进程的SS3:ESP3,随后从CS:IP处开始执行代码。当中断代码执 行完毕后,内核将会从进程堆栈中,将SS3:ESP3、CS:IP弹出,从而回到用户空间重新开始执行,此时并不需要CPU主动来切换级别了;从这里可 知,CPU是需要TSS中的SS0和ESP0来进行高->低级别切换的,因此进程在切换时,必须要将自己的SS0和ESP0保存到 TR->GDTR[i ]->TSS的SS0和ESP0字段中去,其实,在Linux中,对于同一个CPU,所有的进程都使用一个TSS,只是在进程切换时, 被切换到的进程将会把自己的ESP0保存到TSS.ESP0中去(在函数__switch_to中),那为什么不把自己的SS0也保存到TSS.SS0中 呢,这是因为所有进程的SS0都是统一的,为内核的SS,而内核在初始化的时候,已经将该TSS.SS0设置为自己的SS,因此无需继续设置SS0;
  • 至于EFLAGS为什么没有保存,这点在2.6中已经纠正,即执行了pushf和popf;
  • ECX为什么没有保存,则涉及到了如下的理由:i386 ABI / function calling sequence
    Allregisters on the Intel386 are global and thus visible to both a callingand a called function. Registers %ebp, %ebx, %edi,%esi, and %esp'belong' to the calling function. In other words, a called functionmust preserve these registers' values for its caller. Remainingregisters 'belong' to the called function. If a calling function wantsto preserve such a register value across a function call, it must savethe value in its local stack frame.Some registers have assigned rolesin the standard calling sequence:
  • %esp:The stack pointerholds the limit of the current stack frame, which is the address of thestack’s bottom-most, valid word. At all times, the stack pointer shouldpoint to a word-aligned area.
  • ......
  • %ecx and%edx:Scratch registers have no specified role in the standard callingsequence. Functions do not have to preserve their values for the caller.
  • ......

Linux进程管理和X86进程管理的结合
  • 从上面描述中,我们知道X86要求每个进程都必须有自己的TSS,在每次进程切换的时候,通过对应的TR[i ]+GDTRbase找到该进程的TSS,然后保存前一个任务的所有寄存器,同时将找到的TSS中所有的寄存器值恢复到系统对应的寄存器中,从而实现进程切换。
  • 由于Linux实现进程切换的 时候,并不采用该机制,但是却避不过X86这个机制,因此Linux内核设置了init_tss全局变量,在 start_kernel->trap_init->cpu_init初始化时,设置了对应的GDT[i ]指向该init_tss以及TR.index=i;此后,在Linux系统运行过程中,就再也不会改变TR以及该GDT[i ],对应X86来讲,就好像永远运行着1个进程;Linux使用自身的切换机制来实现了进程的切换,这些在上面的文章中已经说明,这里不在多说。
  • 另 一重要问题Linux必须面对:当从高级别切换到低级别时,会引起CPU运行级别的变化,例如从级别3到级别0,此时CPU需要获取0级别的SS0以及 ESP0(例如前面描述的当进程正运行在用户空间时来了个中断范例)来恢复SS:ESP,其设计方法就是从当前的TSS->SS0:ESP0中获 取。为了适应CPU的这种设计,Linux内核在每次switch_to切换进程时,都将被切换来的进程的ESP0保存到init_tss.esp0中; 另外由于Linux内核的SS0始终为KERNEL_SS保持不变,故无需每次切换都将其保存到init_tss.ss0中,只需要在Linux内核初始 化时将init_tss.ss0设置为KERNEL_SS就可以了;

<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
基于QT+Halcon实现线序识别 一、线序识别算法步骤。 1.按照检测区域m_pItem1的外接矩形(rtBount)的大小, 截取感兴趣区域图像hRoi。 2.把截取出来的感兴趣区域图像hRoi, 分离出R、G、B三个通道hRed、hGreen、hBlue。 3.把hRed、hGreen、hBlue三个通道转换成cielab颜色空间, 得到hChannelL、hChannelA、hChannelB三个颜色图。 4.设m_pItem1的宽为iItemW, 高为iItemH. 分别申请大小为iItemW的pSumL、pSumA、pSumB内 阅读详情

相关推荐

Loupe Browser实战指南:解锁10xGenomics单细胞数据的可视化奥秘

本文提供了Loupe Browser的实战指南,帮助用户无需编程即可探索和可视化10xGenomics单细胞数据。文章详细介绍了从数据导入、界面导航到细胞亚群鉴定、差异基因分析的核心操作流程,并分享了高级技巧与避坑指南,是快速上手这一强大可视化工具的必备参考。

weixin_29313423的博客 208

Linux 进程信号 [ 上 ]

就好比你在听到警报声后,根据之前制定的应急计划,迅速找到重要物品并按照预定路线撤离。这是一种经过提前规划和准备的应对方式。在进程里,开发者可以根据需求定义信号的处理逻辑,让进程在接收到信号时执行特定的操作,而不是简单地终止。

Small_entreprene的博客 1268

从勒索软件攻击到数据重生:SQL Server MDF文件修复的实战生存指南

本文详细介绍了SQL Server MDF文件在遭遇勒索软件攻击后的修复策略,重点解析了Recovery Toolbox工具链的应用流程。从灾难评估到数据验证,提供分阶段修复操作、高级修复技术及防御加固方案,帮助企业快速恢复数据库并提升安全防护能力。

weixin_28327051的博客 715

进程间关系与守护进程

本文主要介绍了客户端与服务端之间的自定义协议实现及序列化处理。在前一篇中,我们实现了服务端的代码,本篇补充了客户端的实现。客户端同样需要遵循协议,并通过序列化向服务端发送请求报文,接收服务端返回的序列化应答报文,再通过反序列化获取可读的应答数据。为了实现这一功能,我们进一步完善了 Protocol 类,增加了 GetResponse 接口用于获取服务端应答,以及 BuildRequestString 接口用于构建并序列化请求报文。通过这些接口,客户端能够与服务端进行有效的通信,并处理返回的数据。此外,文章还

Small_entreprene的博客 1106

别再乱调了!Zygo MetroPro软件滤波功能保姆级指南,从均值到鲁棒高斯样条一次讲清

本文深入解析Zygo MetroPro软件的滤波功能,从均值滤波到鲁棒高斯样条等九种算法,帮助用户根据测量对象特性选择最佳滤波组合。通过真实工业案例和参数配置指南,提升光学测量数据的准确性和效率,特别适用于硅晶圆、光学镜片等精密测量场景。

weixin_30888413的博客 158

实证研究之|stata清洗charls数据

stata

qq_45313933的博客 6762

从0到1快速学会Linux操作系统(基础),这一篇就够了!

Linux基础入门:从0到1快速掌握常用操作,这一篇就够了!

「YYL DBA手记」 数据库 · 架构 · 运维 · 实战 yyldba.blog.youkuaiyun.com 5万+

【开发必备插件】iframe嵌套报“拒绝连接请求”的本地解决方法

关键词:iframe 拒绝连接、X-Frame-Options、Chrome 插件、前端调试、Allow X-Frame-Options前几天我在本地项目里调试一个第三方网站的嵌入页面时,遇到了一个非常经典的报错:xxx.com 拒绝了我们的连接请求。熟悉的老前端们一眼就知道——这是。但对于日常开发来说,我们经常需要在本地测试 iframe 嵌套外部页面(比如嵌第三方登录页、支付页、可视化报表系统等)。而线上站点配置了或DENY时,就会直接导致 iframe 加载失败。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1545

Linux用户管理

Linux用户管理

教Linux的李老师 2820

基于STM32的家庭环境监测毕业设计(全部资料)

本文设计并实现了一套基于STM32的家庭环境监测系统,具备温湿度、烟雾浓度和PM2.5检测功能,通过OLED屏实时显示数据,并能自动或手动控制风扇、加湿器等设备。系统采用分层架构设计,包含数据采集、处理、显示和控制执行模块,经测试性能稳定可靠。研究结果表明,该系统能有效提升家庭环境监测与控制的智能化水平,但仍存在传感器精度和智能化程度不足等问题,未来可进一步优化硬件配置并引入AI算法提升性能。

3254968421的博客 462

华为OD机试新系统真题【迷宫相遇】

华为OD机试 新系统真题【迷宫相遇】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【迷宫相遇】多语言题解。

qq_45776114的博客 770

Linux 基础

第一句:定义了组成100ask_led模块的对象文件列表。第二句:编译成一个可加载的内核模块。最终将三个.o文件编译成一个.ko文件内核构建系统会根据。

2301_79302469的博客 782

成功解决 OllamaError: status code 400, message: model ‘llama3.2:latest‘ not found 报错

本文针对Ollama更新后出现的OllamaError: status code 400, message: model 'llama3.2:latest' not found报错,分析了其根本原因——2026年1月Ollama将Llama 3.2模型命名从llama3.2:latest改为meta-llama/Llama-3.2:7b-instruct等新格式。解决方案包括:1)使用新模型名称;2)升级Ollama SDK;3)查询确认本地可用模型;4)批量更新旧项目脚本。通过正确适配新命名规则,

博客 1398

C++ (week4):Linux基础:命令行

Linux简介、vim、Linux命令行、编译工具链

Edward2022的博客 1722

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Linux命令及使用方法new

本文总结了Linux系统管理与开发环境配置的实用技巧,涵盖了常用命令、工具配置和问题解决方法。主要内容包括:Linux基础操作(文件/目录管理、vim编辑器、权限控制);系统资源监控(du/df命令);文本处理(grep/cut/awk);Ubuntu系统问题排查;开发工具链配置(Anaconda/Virtualenvwrapper/Jupyter);终端增强(cmder/Screen);IDE使用(VSCode/Visual Studio);非root权限软件安装;Windows冷门知识;LaTeX语法;

zhjadsf的博客 3217

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

WSL2 shell 使用优化 - 交互响应速度,网络配置

在 WSL2 中,所有涉及 cd 或 prompt 触发的逻辑,必须尽可能避免 Fork 外部进程。能用 Rust/C++ 二进制解决的,绝不用 Shell 脚本。能减少 I/O 往返的,绝不读写磁盘。

WingEdge777的博客 232

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Linux面试题

通过VRRP协议实现主备切换,虚拟IP(VIP)在主节点故障时漂移到备用节点。:磁盘空间不足,如何快速定位大文件?:如何临时修改系统最大打开文件数?访问日志中每个IP的访问次数?仅允许特定IP访问22端口?:如何分析系统负载高的原因?:如何优化TCP连接回收?观察内存使用趋势,结合。:如何检测内存泄漏?

wanglolaini的博客 711

Linux | Bash Shebang 语法与结构及常见问题排查

……

u013669912的博客 1161

Android 性能优化 【总篇:深入浅出】

本篇的主要针对整机性能的一个解读,主要拆解整机性能有哪些小的领域,对应的测试用例是怎么样的,这类问题优化思路是怎么样的。各家厂商针对性能的测试都设计了不同的用例,因此针对性能测试其实是比较五花八门的。我这里凭着经验来总结一下通常都有哪些场景和性能测试相关。

qq_27672101的博客 514

shell常实用命令

利用ssh远程执行服务器命令 fuction expect_server() { expect <<EOF set timeout 1000 spawn $@ expect { "(yes/no)?" {send "yes\r"; exp_continue} "asswor*" {send "${SERVER_PASSWD}\r"; exp_continue} eo...

weixin_41469272的博客 7560

人生最好的php,mysql,linux,redis,docker等相关技术经典面试题,新手收藏学习,持续更新中。。。

php面试题 1、写出你能想到的所有HTTP返回状态值,并说明用途(比如:返回404表示找不到页面) # 200:服务器请求成功 # 301:永久重定向,旧网页已被新网页永久替代 # 302:表示临时性重定向 # 400:错误请求 # 401:未授权,没有权限,未登录 # 403:禁止访问 # 404:找不到页面 # 500:系统错误,服务器错误 # 502:无效响应 # 503:服务不可用,服务器由于维护或者负载过重未能应答 # 504:网关超时(nginx做为反向代理服务器,所连接的应用服务器无响应导致

cxhblog的博客 1万+

SELinux安全子系统

SELinux安全子系统

教Linux的李老师 2831

Ai-Agent学习历程—— 阶段3——RAG 与记忆机制

基于学习大纲我们有了一个简单的地图,从官网的资料进行对应,主要是以下三部分过程中可以进行参考官方文档,但有一些可能会基于目前最新的资料进行适当的更改,让我们愉快的开始吧!这里为您梳理第一节:ETL 数据智能清洗与高阶分块的学习地图。本节将带您攻克数据进入向量数据库之前的“清洗、结构化解析、智能切分与父子文档关联”全流程,彻底打牢 RAG 的数据地基。以现在大模型的发展来说,200K的上下文甚至接近300K的都有,几本书是不成问题的,那切片的意义又在哪?核心原因有三个:在 RAG 系统中,用户提问后,我们不能

蓝桉 861

Python后端开发之旅(五)——DL

pytorch入门操作以及常见的方法和库操作

少年何妨梦摘星,敢挽桑弓射玉衡。 他时若遂凌云志,敢笑黄巢不丈夫。 497

开始还是结束?Linux系统基础操作命令

Linux系统新手小白命令必会系列

。 256

基于Node.js和Vue3的校园博客系统开发实战:从环境搭建到部署避坑指南

全栈开发中,Node.js的事件驱动与异步非阻塞模型为实时通信提供了高效解决方案,而Vue3的组合式API让前端逻辑复用与工程化更加流畅。理解这些技术原理后,可以快速构建一个集博客笔记发布、点赞评论、实时聊天于一体的校园社区系统。文章以真实项目为例,从环境搭建、数据模型设计、JWT鉴权,到Socket.IO消息推送、Nginx多项目部署,完整串联前后端链路。同时针对npm.ps1无法加载、Node.js安装报错2203、WebSocket连接失败、Vue Router刷新404等高频问题给出排查思路。这套N

weixin_34199335的博客 480
上一篇: vi删除操作大全 z
下一篇: 一个简单的网络流量统计程序 z
KataDoc360
博客等级 码龄18年 65粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值