linux下的系统调用和库函数调用

一、linux的结构
在系统调用之前我我们先来了解一下linux系统的结构图:
linux下的系统调用和库函数调用
linux的结构如图:
linux下的系统调用和库函数调用
操作系统在内核的基础上进行延伸,提供了一些基础服务的组件。操作系统是通过驱动程序来管理硬件的,对上就暴露出一些接口,供上层来进行调用,这些接口就被称为系统调用。
shell是被包裹在linux内核的外层,通过一些命令来对操作系统发出指令的人机交互界面。而库函数就是在系统调用的基础上再进行的扩展和封装。
系统调用是操作系统的一部分,在内核中执行。
库函数调用是语言和应用程序的一部分,在用户空间中调用。

二、什么是库函数调用
库函数调用:
标准C库函数如fopen,fread,fwrite等,需要包含stdio.h头文件。库函数是对系统调用的一层封装,底层还是通过系统调用实现的。每打开一个文件所获得的文件指针FILE都有一个内核空间的文件描述符fd与之对应。
库函数就是把函数放在库里面,把一些常用的函数的编写完全放在一个文件里面来供别人使用,别人用的时候把它的文件名加在#include<>里面就可以进行函数的调用。
编译器提供的C源程序的调用的函数分为两类:一类是C标准规定的库函数,另一类是编译器特定的库函数。
库函数分成两类,一类是操作系统提供的,另一类是第三方提供的。
库函数调用通常用于应用程序中对一般文件的访问。
库函数调用是系统无关的,因此可移植性好。
由于库函数调用是基于C库的,因此也就不可能用于内核空间的驱动程序中对设备的操作。

三、什么是系统调用
系统调用:
系统调用是操作系统为用户态运行的进程和硬件设备(CPU、磁盘、打印机)进行交互提供的一个接口。linux内核是单内核,结构紧凑、执行速度快、各个模块之间只直接调用的关系。linux系统的从上到下是:用户进程–>系统调用接口–>linux内核子系统–>硬件也就是linux内核包含了系统调用接口和内核子系统两个部分。从下到上就是:物理硬件–>OS内核–>OS服务–>应用程序。
操作系统为了考虑实现的难度和管理的方便,它只提供一少部分的系统调用,这些系统调用一般都是由C和汇编混合编写实现的,其接口用C来定义,而具体的实现则是汇编,这样的好处就是执行效率高,而且,极大的方便了上层调用。
系统调用通常用于底层文件访问(low-level file access),例如在驱动程序中对设备文件的直接访问。
系统调用是操作系统相关的,因此一般没有跨操作系统的可移植性。
系统调用发生在内核空间,如果在用户空间的一般应用程序中使用系统调用来进行文件操作,那么就会有从用户空间到系统调用的空间切换的开销。库函数对文件的操作实际上是通过系统调用来实现的。例如C库函数fwrite()就是通过write()系统调用来实现的。
那么问题来了,既然库函数有系统调用的开销为什么不直接使用系统调用呢?
这是因为,读写文件通常是大量的数据(这种大量是相对于底层驱动的系统调用所实现的数据操作单位而言),这时,使用库函数就可以大大减少系统调用的次数。
双缓冲技术,在用户空间和内核空间都使用了缓冲区。例如用fwrite进行写操作的时候,先将内容写到用户缓冲区,用户缓冲区满或者写操作结束才把内容从用户缓冲区拿到内核缓冲区。所以,内核缓冲区满的时候或写操作结束才将内容由内核缓冲区拿到对应的硬件媒介。
四、系统调用和库函数调用
区别:
linux下的系统调用和库函数调用
系统调用所提供给用户的是直接而纯粹的高级服务,如果想要更人性化,具有更符合特定情况的功能,那么就要我们用户自己来定义,因此就衍生了库函数,它把部分系统调用包装起来,一方面把系统调用抽象了,一方面方便了用户级的调用。
系统调用和库函数在执行的效果上很相似(当然库函数会更符合需求),但是系统调用是运行于内核状态;而库函数由用户调用,运行于用户态。
系统调用是为了方便使用操作系统的接口,而库函数则是为了人们编程的方便。