当前位置:首页 > 公众号精选 > 码农的荒岛求生

作为上世纪50年代的程序员你是幸福的,因为你写代码时真的是上帝般的存在。

这一时期你编写的代码直接运行在裸机上,你需要自行管理cpu、内存、磁盘和各种外设等资源。

计算机上的所有硬件资源都受你控制,你可以直接硬编码物理内存地址来读写内存、你可以直接控制一段数据写到磁盘的哪个柱面哪个扇区、你可以直接从键盘控制器端口读取键盘按键,就像这样:

mov ax, 0x1000    ; 直接操作物理内存地址0x1000
mov [ax], 0x42    ; 向内存写入数据

in al, 0x60      ; 直接从键盘控制器端口读取按键
mov [0x2000], al ; 保存按键到内存

mov dx, 0x1F0    ; 硬盘控制器端口
mov al, 0x20     ; 读扇区命令
out dx, al       ; 直接操作硬盘

总之,计算机世界里一切都是你说了算,你的代码中充斥着各种硬件细节,这时你不但明白代码这种软件,还对软件运行依赖的底层硬件的每一个细节都了如指掌,对此你深以为傲。

脆弱的系统

然而你很清楚这种高度依赖具体硬件且硬编码的程序是非常脆弱的,这种程序毫无移植性可言,最糟糕的是错误的硬件操作极容易引发系统崩溃。

你开始反思,为什么编写简单的hello world程序还需要关心数据在哪个物理内存地址上、还需要关心磁盘的工作原理、外部设备数据读写这种事情呢?

为什么不把对硬件的操作封装成函数来调用呢?

把细节封装在库中

说干就干,你把所有对硬件操作的底层细节都封装到的函数中,现在大家编程时再也不用必须是硬件专家了。

情况好多了,但即使把所有硬件操作封装在函数中你也避免不了菜鸟程序员想自己发挥一把,如果有人就是不想调用你的库而非要用自己充满bug的代码操作硬件呢?

此时你面临的问题是这样的:操作硬件的代码只能通过库函数调用而不能程序员自己手写。

这怎么可能呢?你还有办法去限制程序员怎么写代码吗?

软件层面考虑是无解了,硬件层面呢?

创世纪

此时你灵光乍现,你发现实际上能操作硬件的关键指令就那么几个,只要规定这几个关键硬件操作指令只能在你实现的库里使用就可以了,其它代码禁止使用这几个指令,这样,想操作硬件就只能借助你的库。

此时问题就变为:怎样限制一部分指令只能由A代码使用而不能让B代码使用。

很简单,你规定CPU执行指令时有两个状态:菜鸟态和专家态,当CPU执行你写的库函数时必须位于专家态,此时CPU可以执行任何指令,包括操作硬件的特权指令;当CPU从你的库中退回到菜鸟态后执行普通程序员写的代码。

当普通程序员试图直接操作硬件时就会触发异常,从而确保只有你的库能操作硬件。

很好,现在只剩下最后一个问题,那就是CPU怎么知道什么时候在菜鸟态和专家态之间进行切换呢?

简单,你规定当普通程序员调用你的库操作硬件时必须通过一条特殊的机器指令,当CPU执行这条特殊指令时就会跳转到你的库中并切换到专家态,就像这样:

int 0x80   ; 切换到专家态
iret       ; 退回到菜鸟态  

通过库函数加CPU执行状态这种机制,你成功的限制了菜鸟程序员向硬件专家迈进的冲动,普通程序员再也没办法直接操作硬件把系统搞崩溃了。

就这样你发明了一个很聪明的机制,总得有个名字,你实现的库就叫做操作系统吧,operating system;CPU的菜鸟态和专家态听上去太low了,就叫内核态和用户态。

由于调用你的库(operating system)和普通的函数调用差不多,普通的函数调用叫做function call,调用操作系统就叫做system call(系统调用)吧。

就这样你发明了系统调用,顺便发明了操作系统。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭