首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

linux内核系统调用和标准C库函数的关系分析

linux内核系统调用和标准C库函数的关系分析

1.系统调用是为了方便应用使用操作系统的接口,而库函数是为了方便人们编写应用程序而引出的,比如你自己编写一个函数其实也可以说就是一个库函数。
2.系统调用可以理解为内核提供给我们在用户态用的接口函数,可以认为是某种内核的库函数。
3.read就是系统调用,而fread就是C标准库函数.
4.很多c函数库中的函数名与系统调用的名称一样是因为该函数本身其实就是调用的系统调用,放到c函数库就是为了用户态的使用
5.写程序直接使用的是库函数,而库函数内部可能就是调用的同名系统调用
6.首先,现在的OS内核主要采用两种模式,整体的单内核模式(linux)和分层的微内核模式(Windows)。单内核
模式的特点就是代码紧凑,执行速度快,各个模块之间是直接的调用关系,可以说最后一点既是优点,也是缺
点...有点就是执行速度快,缺点是内核看起来很乱,维护起来困难。
无论是单内核,还是微内核,立体的体系结构从下到上大概都是分成这样几层:物理硬件,OS内核,OS服务,
应用程序。这四层结构中,OS内核起到一个“承上启下”的作用,向下管理物理硬件;向上为OS服务和应用程序
提供接口。主意,这里的接口实际上是指系统调用(System Call)。
通常OS内核为了考虑实现起来的难度和易于管理,只提供少部分必要的系统调用,这些系统调用通常都是C和
汇编混编来实现的。接口用C定义,实现体用汇编来写。这样做的好处是,执行效率高,并且极大的方便了上层的
调用。
再说库函数(即API)。库函数可以概括的分为两类,一类是随OS提供的,另一类是第三方的。随系统提供的库
函数进一步封装或组合系统调用,实现更多的功能,就像用C语言的许多功能单一的小函数来实现很多很多个功能
复杂的大函数一样。这样的API能够执行一些相对内核来说很复杂的操作,比如,read()函数根据参数,直接就
能读文件,而背后隐藏的比如文件在硬盘的哪个磁道,哪个扇区,加载到内存的哪个位置等等这些操作,程序员
是不必关心的,这些操作里面自然也包含了系统调用。而对于第三方的库,它其实和系统库一样,只是它直接利
用系统调用的可能性要小一些,而是利用系统提供的API接口来实现功能。(API的接口是开放的)
7.高级语言库函数的确是调用系统调用来实现的,所以说系统调用才是真正对硬件操作的。
但是大家可能注意到了为什么库函数为什么是通用的(同名),这是正是高级语言不依赖与特定的硬件。
其实,都是编译器来负责库函数到系统调用之间的转换的。比如说VC可能通过把fopen()对应到windows的打印系统调用XXX(不知道具体是哪个)上去了,而linux的编译器gcc通过把fopen()对应到linux的系统调用open上去了。
8.系统调用没有库函数的效率高是因为与设置的缓冲池大小有关吧,缓冲池(不知是用户的还是内核的)小的话,系统调用的操作就频繁,缓冲池(不知是用户的还是内核)大的的话,库函数就调用系统调用的次数就少。
9.应用程序可以直接调用库函数来操作。那么linux的源代码C里是不应该使用库函数的吧,你想。编译连接成内核镜像后,安装在裸机上,连个运行环境都没怎么系统调用啊。有的人会说,系统调用在编译连接的时候已经把系统调用弄进去了,那么不是说现在流行的动态连接吗,直到运行需要时才去连接吗。
论坛的人基本就是以上的观点.
有些混乱,这里参考了下<>的第五章,关于系统调用的一些内容,如下:
第5章 系统调用
大部分介绍Linux内核的书籍都没有仔细说明系统调用,这应该算是一个失误。内核发展到现在,我们实际需要的系统调用现在已经十分完美,从这个意义上来说,再耗费宝贵的时间去研究系统调用的实现是毫无意义的事情。
然而,对于希望能够对内核有更深理解的我们来说,仔细研究少量系统调用仍是十分值得的。这样就有机会初步了解一些概念,并可以趁机详细了解一下内核编程的特点,就像系统调用本身在应用程序和内核间的桥梁作用一样,学习并理解它也是我们走向内核的一个很好的过渡。
5.1 系统调用概述
一个稳定运行的Linux操作系统需要内核和用户应用程序之间的完美配合,内核提供各种各样的服务,然后用户应用程序通过某种途径使用这些服务,进而契合用户的不同需求。
用户应用程序访问并使用内核所提供的各种服务的途径即是系统调用。在内核和用户应用程序相交界的地方,内核提供了一组系统调用接口,通过这组接口,应用程序可以访问系统硬件和各种操作系统资源。比如用户可以通过文件系统相关的系统调用,请求系统打开文件、关闭文件或读写文件;可以通过时钟相关的系统调用,获得系统时间或设置定时器等。
内核提供的这组系统调用通常也被称之为系统调用接口层。系统调用接口层作为内核和用户应用程序之间的中间层,扮演了一个桥梁,或者说中间人的角色。系统调用把应用程序的请求传达给内核,待内核处理完请求后再将处理结果返回给应用程序。
5.1.1  系统调用、POSIX、C库、系统命令和内核函数
(1)系统调用和POSIX。
系统调用虽然是内核和用户应用程序之间的沟通桥梁,是用户应用程序访问内核的入口点,但通常情况下,应用程序是通过操作系统提供的应用编程接口(API)而不是直接通过系统调用来编程。
操作系统API的主要作用是把操作系统的功能完全展示出来,提供给应用程序,基于该操作系统,与文件、内存、时钟、网络、图形、各种外设等互操作的能力。此外,操作系统API通常还提供许多工具类的功能,比如操纵字符串、各种数据类型、时间日期等。
在UNIX世界里,最通用的操作系统API基于POSIX(Portable Operating System Interface of UNIX,可移植操作系统接口)标准。POSIX的诞生和UNIX的发展密不可分,UNIX于20世纪70年代诞生于Bell lab,并于20世纪80年代向美各大高校分发V7版的源码以做研究。UC Berkeley在V7的基础上开发了BSD UNIX。
后来很多商业厂家意识到UNIX的价值也纷纷以Bell Lab的System V或BSD为基础来开发自己的UNIX,较著名的有Sun OS、AIX、VMS等。虽然这带来了UNIX的繁荣,但由于各厂家对UNIX的开发各自为政,UNIX的版本相当混乱,给软件的可移植性带来很大困难,对UNIX的发展极为不利。
为结束这种局面,IEEE制订了POSIX标准,目标是提供一套大体上基于UNIX的可移植操作系统标准,提高UNIX环境下应用程序的可移植性。然而,POSIX并不局限于UNIX。许多其他的操作系统,例如DEC OpenVMS和Microsoft Windows NT,都支持POSIX标准
POSIX标准定义了"POSIX兼容"的操作系统所必须提供的服务。Linux兼容于POSIX标准,提供了根据POSIX而定义的API函数。这些API函数和系统调用之间有着直接的关系,一个API函数可以由一个系统调用实现,也可以通过调用多个系统调用来实现,还可以完全不使用任何系统调用。
(2)系统调用和C库
操作系统API通常都以C库的方式提供,Linux也是如此。C库提供了POSIX的绝大部分API,同时,内核提供的每个系统调用在C库中都具有相应的封装函数。系统调用与其C库封装函数的名称常常相同,比如,read系统调用在C库中的封装函数即为read函数。
C库中的系统调用封装函数在最终调用到相应系统调用之前,往往不做多少额外的工作。不过,某些情况下会有些例外,比如对于两个相关的系统调用truncate和truncate64,C库中的封装函数truncate函数即需要决定它们中的哪个应该最终被调用。
当然,如图5.1所示,系统调用和C库函数之间并不是一一对应的关系。可能几个不同的函数会调用到同一个系统调用,比如malloc函数和free函数都是通过brk系统调用来扩大或缩小进程的堆栈,execl、execlp、execle、execv、execvp和execve函数都是通过execve系统调用来执行一个可执行文件。
有可能一个函数调用多个系统调用更有些函数并不依赖于任何系统调用,比如strcpy函数(复制字符串)和atoi函数(转换ASCII为整数),因为它们并不需要向内核请求任何服务

图5.1  C库函数与系统调用
实际上,从用户的角度看,系统调用和C库之间的区别并不重要,他们只需通过C库函数完成所需功能。相反,从内核的角度看,需要考虑的则是提供哪些针对确定目的的系统调用,并不需要关注它们如何被使用。
3)系统调用与系统命令。
系统命令位于C库的更上层,是利用C库实现的可执行程序,比如最为常用的ls、cd等命令。
strace工具可以跟踪命令的执行,使用希望跟踪的命令为参数,并显示出该命令执行过程中所使用到的所有系统调用。比如,如果希望了解在执行pwd命令时都调用了哪些系统调用,可以使用下面的命令:
  
       
  • $strace pwd
结果会产生大量的信息,显示出pwd命令执行过程中所调用到的各个系统调用:
  
       
  • ……
  • write(1, "/usr/src/linux-2.6.23/n", 22/usr/src/linux-2.6.23) = 22
  • close(1)                                = 0
  • munmap(0xb7f5a000, 4096)                = 0
  • exit_group(0)
(4)系统调用和内核函数。
内核函数与C库函数的区别仅仅是内核函数在内核实现,因此必须遵守内核编程的规则。
系统调用最终必须具有明确的操作。用户应用程序通过系统调用进入内核后,会执行各个系统调用对应的内核函数,即系统调用服务例程,比如系统调用getpid的服务例程是内核函数sys_getpid。
系统调用服务例程之外,内核中存在着大量的内核函数。有些局限于某个内核文件自己使用,有些则是export出来供内核其他部分共同使用。对于export出来的内核函数,可以使用ksyms命令或通过/proc/ksyms文件查看
说白了,系统调用是内核提供的接口,而不管是系统命令还是标准库函数,都是基于系统调用编写的应用程序,只不过是一些大牛写的啦,程序健壮,够标准,哈哈,我们自己也可以写用户程序做为自己的库函数,自己在内核代码中添加系统调用,这些都是可以做到的
继承事业,薪火相传
返回列表