系统调用和库函数

系统调用概述:

系统调用,我们可以理解是操作系统为用户提供的一系列操作的接口(API),这些接口提供了对系统硬件设备功能的操作。这么说可能会比较抽象,举个例子,我们最熟悉的 hello world 程序会在屏幕上打印出信息。程序中调用了 printf() 函数,而库函数 printf 本质上是调用了系统调用 write() 函数,实现了终端信息的打印功能。

用户应用程序访问并使用内核所提供的各种服务的途径即是系统调用。在内核和用户应用程序相交界的地方,内核提供了一组系统调用接口,通过这组接口,应用程序可以访问系统硬件和各种操作系统资源。
系统调用可以理解为内核提供给我们在用户态用的接口函数,可以认为是某种内核的库函数。

内核提供的这组系统调用通常也被称之为系统调用接口层。系统调用接口层作为内核和用户应用程序之间的中间层,扮演了一个桥梁,或者说中间人的角色。系统调用把应用程序的请求传达给内核,待内核处理完请求后再将处理结果返回给应用程序。

系统调用虽然是内核和用户应用程序之间的沟通桥梁,是用户应用程序访问内核的入口点,但通常情况下,应用程序是通过操作系统提供的应用编程接口(API)而不是直接通过系统调用来编程。
操作系统API通常都以C库的方式提供,Linux也是如此。C库提供了POSIX的绝大部分API,同时,内核提供的每个系统调用在C库中都具有相应的封装函数。系统调用与其C库封装函数的名称常常相同,比如,read系统调用在C库中的封装函数即为read函数。

很多c函数库中的函数名与系统调用的名称一样是因为该函数本身其实就是调用的系统调用,放到c函数库就是为了用户态的使用

写程序直接使用的是库函数,而库函数内部可能就是调用的同名系统调用

首先,现在的OS内核主要采用两种模式,整体的单内核模式(linux)和分层的微内核模式(Windows)。单内核
模式的特点就是代码紧凑,执行速度快,各个模块之间是直接的调用关系,可以说最后一点既是优点,也是缺
点…有点就是执行速度快,缺点是内核看起来很乱,维护起来困难。
无论是单内核,还是微内核,立体的体系结构从下到上大概都是分成这样几层:物理硬件,OS内核,OS服务,
应用程序。这四层结构中,OS内核起到一个“承上启下”的作用,向下管理物理硬件;向上为OS服务和应用程序
提供接口。主意,这里的接口实际上是指系统调用(System Call)。
通常OS内核为了考虑实现起来的难度和易于管理,只提供少部分必要的系统调用,这些系统调用通常都是C和
汇编混编来实现的。接口用C定义,实现体用汇编来写。这样做的好处是,执行效率高,并且极大的方便了上层的
调用。

再说库函数(即API)。库函数可以概括的分为两类,一类是随OS提供的,另一类是第三方的。随系统提供的库
函数进一步封装或组合系统调用,实现更多的功能,就像用C语言的许多功能单一的小函数来实现很多很多个功能
复杂的大函数一样。这样的API能够执行一些相对内核来说很复杂的操作,比如,read()函数根据参数,直接就
能读文件,而背后隐藏的比如文件在硬盘的哪个磁道,哪个扇区,加载到内存的哪个位置等等这些操作,程序员
是不必关心的,这些操作里面自然也包含了系统调用。而对于第三方的库,它其实和系统库一样,只是它直接利
用系统调用的可能性要小一些,而是利用系统提供的API接口来实现功能。(API的接口是开放的)

库函数概述

库函数可以理解为是对系统调用的一层封装。系统调用作为内核提供给用户程序的接口,它的执行效率是比较高效而精简的,但有时我们需要对获取的信息进行更复杂的处理,或更人性化的需要,我们把这些处理过程封装成一个函数再提供给程序员,更方便于程序猿编码。

库函数有可能包含有一个系统调用,有可能有好几个系统调用,当然也有可能没有系统调用,比如有些操作不需要涉及内核的功能。可以参考下图来理解库函数与系统调用的关系。

库函数和操作系统的关系
函数库调用是语言或应用程序的一部分,而系统调用是操作系统的一部分

所有 C 函数库是相同的,而各个操作系统的系统调用是不同的。
函数库调用是调用函数库中的一个程序,而系统调用是调用系统内核的服务。
函数库调用是与用户程序相联系,而系统调用是操作系统的一个进入点
函数库调用是在用户地址空间执行,而系统调用是在内核地址空间执行
函数库调用的运行时间属于「用户」时间,而系统调用的运行时间属于「系统」时间
函数库调用属于过程调用,开销较小,而系统调用需要切换到内核上下文环境然后切换回来,开销较大
在C函数库libc中大约 300 个程序,在 UNIX 中大约有 90 个系统调用
函数库典型的 C 函数:system, fprintf, malloc,而典型的系统调用:chdir, fork, write, brk

库函数调用大概花费时间为半微妙,而系统调用所需要的时间大约是库函数调用的 70 倍(35微秒),因为系统调用会有内核上下文切换的开销。纯粹从性能上考虑,你应该尽可能地减少系统调用的数量,但是,你必须记住许多 C 函数库中的程序通过系统调用来实现功能。

首先解释,上述说明的库函数性能远高于系统调用的前提是,库函数种没有使用系统调用。再来解释下某些包含系统调用的库函数,然而其性能确实也要高于系统调用。比如上篇文章中关于文件 IO 函数 fread、fwrite、fputc、fgetc 等,这些函数通常情况下性能确实比系统调用高,原因在于这些库函数使用了缓冲区,减少了系统调用的次数,因而显得性能比较高。

系统调用

当一个进程正在运行,遇到读写文件操作,会发生一个中断,中断后系统会把当前用户进程的一些寄存器信息保存在内核堆栈中,接着去处理中断服务程序,这里是要去执行系统调用,Linux 中通过执行 int $0x80 来执行系统调用的中断,但内核实现了很多系统调用,这时需要传递「系统调用号」来指明需要哪个系统调用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值