一、系统调用上周总结了《C 标准库的基础 IO》,其实这些功能函数通过「系统调用」也能实现相应功能。这次文章并不是要详细介绍各系统调用接口的使用方法,而是要深入理解「库函数」与「系统」调用之间的关系和区别。
系统调用,我们可以理解是 *** 作系统为用户提供的一系列 *** 作的接口(API),这些接口提供了对系统硬件设备功能的 *** 作。这么说可能会比较抽象,举个例子,我们最熟悉的 hello world
程序会在屏幕上打印出信息。程序中调用了 printf()
函数,而库函数 printf
本质上是调用了系统调用 write()
函数,实现了终端信息的打印功能。
库函数可以理解为是对系统调用的一层封装。系统调用作为内核提供给用户程序的接口,它的执行效率是比较高效而精简的,但有时我们需要对获取的信息进行更复杂的处理,或更人性化的需要,我们把这些处理过程封装成一个函数再提供给程序员,更方便于程序猿编码。
库函数有可能包含有一个系统调用,有可能有好几个系统调用,当然也有可能没有系统调用,比如有些 *** 作不需要涉及内核的功能。可以参考下图来理解库函数与系统调用的关系。
hello world
程序是将信息打印到终端,终端对系统来说是硬件资源,如果没有系统调用,用户程序需要自己编写终端设备的驱动,以及控制终端如何显示的代码。隐藏背后的技术细节。比如读写文件,如果使用了系统调用,用户程序无须关心数据在磁盘的哪个磁道和扇区,以及数据要加载到内存什么位置。保证系统的安全性和稳定性。要知道用户程序是不能直接 *** 作内核地址空间的,比如一个刚出道的程序猿,让他直接去访问内核底层的数据,那么内核系统的安全性就无法保证。而系统调用的功能是由内核来实现,用户只需要调用接口,无需关心细节,也避免了系统的安全隐患。方便程序的移植性。如果针对一个系统资源的功能 *** 作比如 write(),大家都按照自己思路去实现这个功能,那么我们写出来的程序的移植性就会非常差。总而言之,我们只需要把系统调用当作一个接口,而这个接口能实现我们的一个功能,既方便又安全。
四、库函数 vs 系统调用参考了《C 专家编程》书籍中的附录 A.4,书中关于两者区别的回答是这样的,函数库调用是语言或应用程序的一部分,而系统调用是 *** 作系统的一部分。
所有 C 函数库是相同的,而各个 *** 作系统的系统调用是不同的。函数库调用是调用函数库中的一个程序,而系统调用是调用系统内核的服务。函数库调用是与用户程序相联系,而系统调用是 *** 作系统的一个进入点函数库调用是在用户地址空间执行,而系统调用是在内核地址空间执行函数库调用的运行时间属于「用户」时间,而系统调用的运行时间属于「系统」时间函数库调用属于过程调用,开销较小,而系统调用需要切换到内核上下文环境然后切换回来,开销较大在C函数库libc中大约 300 个程序,在 UNIX 中大约有 90 个系统调用函数库典型的 C 函数:system,fprintf,malloc,而典型的系统调用:chdir,fork,write,brk据书中记载,库函数调用大概花费时间为半微妙,而系统调用所需要的时间大约是库函数调用的 70 倍(35微秒),因为系统调用会有内核上下文切换的开销。纯粹从性能上考虑,你应该尽可能地减少系统调用的数量,但是,你必须记住许多 C 函数库中的程序通过系统调用来实现功能。
五、正确理解库函数高效于系统调用首先解释,上述说明的库函数性能远高于系统调用的前提是,库函数种没有使用系统调用。再来解释下某些包含系统调用的库函数,然而其性能确实也要高于系统调用。比如上篇文章中关于文件 IO 函数 fread、fwrite、fputc、fgetc 等,这些函数通常情况下性能确实比系统调用高,原因在于这些库函数使用了缓冲区,减少了系统调用的次数,因而显得性能比较高。
六、系统调用是如何运行的上述内容基本说清楚了库函数与系统调用的概念以及它们之间的关系,下面我们来理解系统调用到底是如何运行的。
当一个进程正在运行,遇到读写文件 *** 作,会发生一个中断,中断后系统会把当前用户进程的一些寄存器信息保存在内核堆栈中,接着去处理中断服务程序,这里是要去执行系统调用,linux 中通过执行 int
来执行系统调用的中断,但内核实现了很多系统调用,这时需要传递「系统调用号」来指明需要哪个系统调用。int main(){ time_t tt; struct tm *t; asm volatile ( "mov
x80mov
,%%ebx\n\t" "mov %eax
xd %%eaxint x80
xd,%%eax\n\t" "int x80\n\t" "mov %%eax,%0\n\t" : "=m" (tt) ); t = localtime(&tt); printf("Time: %d-%02d-%02d %02d:%02d:%02d\n",t->tm_year + 1900,t->tm_mon + 1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);}[linuxblogs@host ~]$ gcc a.c -oa && ./aTime: 2018-05-06 03:23:46
为了更清楚的说明系统调用的过程,我们这里参考网上的一段代码来实现系统调用:
首先通过 来将系统调用放入 寄存器中,time() 的系统调用号是 13,然后执行 系统就会去执行 time() 这个系统调用了。其实代码中的汇编部分就是实现 time() 系统调用的功能,汇编代码不懂没关系(我也不太懂),这里主要是为了说清楚系统调用的整个过程。
欢迎关注公众号: 「linuxblogs」 总结以上是内存溢出为你收集整理的Linux 库函数与系统调用的关系与区别全部内容,希望文章能够帮你解决Linux 库函数与系统调用的关系与区别所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)