小T成长记-操作系统篇1-一条小小的除法指令引起的翻车事故

1 事故背景

  • 人物:小T(研发中心-操作系统开发工程师);小S(产品开发部-软件工程师)
  • 背景:公司正在联合开发基于MIPS架构的产品。研发中心负责操作系统平台开发,产品开发部负责业务逻辑开发。目前操作系统已经进入试用阶段。

2 事故现场

操作系统上线后,一直比较稳定。小T泡上一杯茶,正在浏览着天下大事,心里那个美啊!

“叮铃铃...叮铃铃...”,小T不仅被电话铃声吓了一跳,“谁啊,这么烦”,心里不禁咒骂了一句,不情愿地拿起了桌上的电话,“您好,请问哪位?”。

“小T,我是小S啊!出大事了,咱们的系统网络通信任务消失了,但是系统还在正常跑,其它任务也能工作。是不是咱们的操作系统出问题了啊?”听得出,小S现在是心急如焚。

听到这里,小T额头上的汗珠都下了。操作系统不能正常工作,这可是重大事故啊,弄不好又得被领导批,哎,“别急,把当时的工程代码发给我,我分析看看”小T对小S说。

拿到测试工程,加载运行。若干时间后,网络服务器与客户端的通信自动停止了。

3 确定问题

既然是网络任务不正常,那就先从网络开始分析吧!

首先,分析测试工程中对socket套接字使用;然后是,监控网络协议栈中的数据收发过程;最后是网络驱动程序的数据收发。然而,一无所获。

难道是进程调度算法有问题?于是,小T打印了系统运行中所有任务的调度过程,发现除了网络任务之外都是正常的,网络任务停止的时候,scheduler()调度器中确实没有了相关的进程信息。那说明,调度算法也没啥问题啊。到底是哪里的问题呢?

小T毕竟是一个有着过硬心理素质的人,怎么可能被这点问题吓到呢。他的信条就是,“没有解决不了的bug,如果有,肯定是遗漏了什么重要线索。”

于是,从头梳理。采用最简单粗暴的方式,在网络任务里采用标记法,确认任务停止调度的时候到底停在了哪里。通过打印信息发现,每次都停在了网络数据包(64K)进行CRC32校验的过程中。继续检查CRC32校验算法(本身算法已经用了好多年,不会出问题)。最终发现CRC校验算法中使用了除法/指令,计算需要计算CRC值的次数,正常的时候这个值是正确的;停止调度的时候,这个值是一个巨大的数值。本身这个值会被作为索引访问数组,导致越界,破坏了任务堆栈。

终于找到了根源,就好办了。小T查阅MIPS架构的除法指令,找到了这么一段内容:

A computed result written to the HI/LO pair by DIV, DIVU, MULT, or MULTU must be read by MFHI or MFLO before a new result can be written into either HI or LO. If an MTLO instruction is executed following one of these arithmetic instructions, but before an MFLO or MFHI instruction, the contents of HI are UNPREDICTABLE.

The following example shows this illegal situation:

MUL r2,r4 # start operation that will eventually write to HI,LO
...       # code not containing mfhi or mflo
MTLO r6
...       # code not containing mfhi
MFHI r3   # this mfhi would get an UNPREDICTABLE value

上面翻译成中文就是:

DIVDIVUMULTMULTU等乘除法指令,会将计算结果写入HI/LO这一对寄存器中,在下次做乘除法之前,必须使用指令MFHIMFLO将结果取走。如果在乘除算术指令和MFHIMFLO指令之间,调用MTLO指令写LO寄存器,那么HI寄存器的内容是不可预测的。

下面是非法情况的一个示例

MUL r2,r4 # r2和r4相乘,结果写入HI、LO
...       # 此处没有调用mfhi和mflo
MTLO r6   # 将r6的值写入LO
...       # 此处没有调用mfhi
MFHI r3   # r3的值不可预测

这就是CRC32校验中,计算的次数为什么会出现一个巨大值的原因:多任务系统中,调用乘除法指令的地方发生冲突,如果进程上下文切换中,没有保护HI/LO寄存器的内容,就会发生不可预料的结果。

小T马上review进程上下文切换的代码,发现确实只保护了通用寄存器,而忽略了这个特殊寄存器。

......(敲击键盘的清脆声,此起彼伏)

修改完代码,下载程序,启动可靠性测试后。小T陷入了深深的反思之中,暗暗懊悔自己的粗心大意,对文档的似是而非。

附在文末:

作者才疏学浅,只是按照自己的理解,采用叙事的手法,把对于网络的学习过程,重新进行学习归纳,以达到融会贯通的目的。
这会是一个序列,包括网卡设备、网络驱动、操作系统以及网络安全等方面的知识。直到菜鸟小T成长为一个网络方面的高手为止。但是,身在江湖,身不由己。工作有时候会很繁忙,也许更新会很慢,希望大家理解。
文中的菜鸟小T,其实就是作者自己,因为自己的英文名称为Tupelo(山茱萸,一种生命力旺盛的药科植物,果实还挺好看的)。至于老鸟嘛,是很多帮助过作者的一个人物抽象。在此,在此感谢学习阶段的各位老师,工作后的各位同事。
下面是作者的微信公众号,为了交流学习试用,欢迎大家保存关注。在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值