查看原文
其他

【OS】原来应用是这样访问到底层(系统调用)

bug菌 最后一个bug 2021-01-31

1、聊一聊

    今天为大家推荐一首许嵩的<小烦恼没什么大不了>,其中歌曲中的几句歌词挺不错的,"......唱不了的歌就转调,千万不要自寻烦恼......不属于你的就不要,快乐不靠拥有多少......",要保持平和的心态,不然血压容易升高。

2、OS对硬件的隐蔽

    为什么今天介绍系统调用呢?目前大家都在学习研究linux,在学习过程中面对这么大一个操作系统,给大家最大的疑惑就是应用程序是如何把信息传递到底层然后驱动硬件的,也算是对系统的一个整体的把握吧。所以,作者结合之前自己的学习经验只要理解什么叫系统调用就能解开大部分的疑惑了。

    大家平时使用的window系统就知道,只要是window应用程序都可以在装有windows系统的不同CPU上运行。有些玩MCU小伙伴又该有疑问了,RTOS不能在任何MCU上运行,需要移植,只能说对于两种OS差距不是一个数量级。OS为用户非常隐蔽的管理好了底层硬件,对于linux而言其抽象出来就是一句话:"一切皆文件",那么下面我们打开用户到OS的第一道门---系统调用。


3、什么是系统调用

    系统调用简单一点说就是应用程序访问内核的一套接口,不过我们一般会首先访问库函数,如下图所示:

解析一下:
  • 从作者看来其实linux系统内部大量采用着面向对象的软件设计方法,大家可以把应用程序和OS内核(Kernal)分别看成两个对象,应用程序通过系统调用通知内核提供相应服务,同时内核也会对消息进行检查处理,从而保证系统的安全。

  • 应用程序大部分都是调用的库函数也可以认为就是API接口,像windowsAPI可就多了,对于linux也不例外,比如常用的Open/Read/Write、printf等等,然而这些库函数内部大部分都是由一个或者多个系统调用构成的,如果仅仅只是数值计算的库函数那就不需要调用系统调用了。

  • 进程是不能直接访问kernal的内存或者调用其函数的,这样保证了系统的安全性,同时只需要提供同一套系统调用便可以运行相同应用程序,所以这和单片机中的RTOS还是有很大的区别,RTOS的任务可以访问OS中的几乎任意位置,不过由于单片机的资源有限,这样可以节省更多的中断时间。

3、系统调用过程分析

    大家玩过RTOS都知道我们在平时进行任务切换大部分都会通过触发软件中断来进行任务的调度,其实系统调用跟软件中断是非常类似的,只是说系统调用通过触发中断由用户态切换到了内核态。

解析一下:
  • 作者这里简单描述一下该过程:1)应用调用库函数;2)库函数中调用系统调用接口;3)系统调用触发软件中断;4)进入内核态通过判断系统调用号,在系统调用表中找到对应的服务函数入口地址,然后执行对应的系统调用服务函数(不同的调用号对应着不同功能的服务函数).

  • 从用户态切换到内核态为了不破坏之前的应用程序运行需要保存中断现场,同时在中断服务函数结束以后需要恢复现场,这个跟RTOS中的调度过程是一致的。

4、系统调用参数传递

    为了确保安全访问,用户态和内核态分别有各自的堆栈,当触发软件中断以后内核态不能直接使用用户态堆栈,也不能直接使用内核态堆栈,因为内核态堆栈并没有用户态传递的数据,那么系统调用如何传递参数的呢?

解析一下:
  • 参数的传递主要通过寄存器来完成,在用户态依次把所要传递的参数存入寄存器中,同时也包括系统调用号等。

  • 当进入内核态以后把各个寄存器压入内核态堆栈,那么系统调用服务函数便可以根据约定找到对应的参数使用,对于多于寄存器个数的参数可以通过使用寄存器作为地址来进行处理。

5、最后小结

    大家应该对应用程序如果通过操作系统到设备底层应该有一个宏观的概念了吧,同时大家也可以自定义系统调用来实现自己需求。

    好了,这里是公众号:“最后一个bug”,一个为大家打造的技术知识提升基地。同时非常感谢各位小伙伴的支持,我们下期精彩见!

推荐好文  点击蓝色字体即可跳转

【重磅】“整形数”还真没那么简单(C语言版)

 【解惑】到底是"时间片"?还是"分时轮询"?

【经典】"有格调"的MCU初始化(绝对要get)

【重磅】剖析MCU的IAP升级软件设计(设计思路篇)

☞ 【典藏】别怪"浮点数"太坑(C语言版本)

GUI必备知识之“告别”乱码(浅显易懂)

【典藏】大佬们都在用的结构体进阶小技巧

听说因为代码没"对齐"程序就奔了?(深度剖析)

【典藏】自制小型GUI界面框架(设计思想篇)

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存