1.11.系统调用和库函数(System Calls and Library Functions)

1.11.系统调用和库函数(System Calls and Library Functions)

所有的操作系统都提供服务点(service points),程序通过服务点向内核请求服务。UNIX系统的所有实现都提供经良好定义的有限数目的入口点(a well-defined, limited number of entry points),这些入口点是directly into the kernel的,叫做系统调用(system calls)。Research UNIX System的版本7提供大约50个系统调用,4.4BSD提供大约110个,SVR4提供大约120个。无论何种版本的Linux都能提供240到260个系统调用,具体多少个要看是哪个版本。FreeBSD提供大约320个。


系统调用接口(system call interface)总是在《UNIX程序员手册》的第2部分中说明(documented in Section 2 of the UNIX Programmer's Manual,就是man 2的那些函数?)。{系统调用称为接口可以有figure1.1和第一段中看出,它是内核对外的接口}无论任何一个给定的系统使用何种实际的实现技术去调用系统调用,系统调用的实现都是用C写的(Its definition is in the C language.该处是否是这个意思?)。这与许多早期的操作系统不同,它们传统上是使用机器的汇编语言写的这些内核入口点(kernel entry points)。

UNIX系统所使用的技术是为每个系统调用在标准C库中设置一个具有同样名字的函数。用户的进程用标准C调用序列(standard C calling sequence)来调用这些函数。然后,这些函数又用系统所要求的技术调用相应的内核服务。例如,函数可将一个或多个C参数送入通用寄存器,然后执行某个在内核中产生软中断(software interrupt)的机器指令。从应用角度考虑,可将系统调用视作为C函数。

《UNIX程序员手册》的第3 section定义了程序员可以使用的通用函数(general-purpose functions)。虽然这些函数可能会调用一个或多个内核的系统调用,但是它们并不是内核的入口点(entry points into the kernel)。例如, printf函数可能会使用write系统调用以输出一个字符串,但函数strcpy (复制一字符串)和atoi(转换ASCII为整数)并不使用任何系统调用。

从实现者(implementor)的角度来看,系统调用和库函数之间有重大区别。但从用户角度来看,其区别并不非常重要(critical)。在本书中,系统调用和库函数都以正常的C函数的形式出现。两者都对应用程序提供服务。但是,我们应当认识到,如果需要的话,我们可以替换库函数,但是通常却不能替换系统调用。

以内存分配函数(memory allocation function)malloc为例。有多种方法可以进行内存分配及与其相关的无用区收集操作(最佳适应,首次适应等)(garbage collection (best fit, first fit, and so on))。并不存在对所有程序都最佳的一种技术。UNIX系统调用中处理内存分配的是sbrk(2),它不是一个通用的内存管理器(general-purpose memory manager)。它增加或减少指定字节数的进程地址空间。如何管理该地址空间却取决于进程。内存分配函数malloc(3)实现了一种特定类型的分配。如果我们不喜欢其操作方式,则可以定义自己的malloc函数,它可能将使用sbrk系统调用。事实上,有很多软件包通过使用sbrk系统调用实现了它们自己的内存分配算法。图figure1.11显示了应用程序,malloc函数以及sbrk系统调用之间的关系。

从中可以清楚的看见,库函数malloc和系统调用sbrk职责不同,相互分开。内核中的系统调用分配另外一块空间给进程,而库函数malloc则从用户级别管理这一空间。

另一个可说明系统调用和库函数之间的差别的例子是,UNIX系统提供的确定当前时间和日期的接口。某些操作系统提供一个系统调用以返回时间,提供另一个返回日期。任何特殊的处理,例如正常时制和夏时制之间的转换,由内核处理或要求人为干预。UNIX系统则不同,它只提供一条系统调用,该系统调用返回自国际标准时间1970年1月1日零点以来所经过的秒数。对该值的任何解释,比如将其转换成人们可读的,使用本地时区的时间和日期,都留给用户进程处理。在标准C库中,提供了若干例程(routines)以处理大多数情况。这些库函数处理各种细节,例如各种夏时制算法。

一个应用程序可以调用系统调用或者库函数。而很多库函数都会调用系统调用。这在图figure1.12中显示。


系统调用和库函数之间的另一个差别是:系统调用通常提供一个最小接口,而库函数通常提供比较复杂的功能。我们已经从sbrk系统调用和malloc库函数之间的差别看到这一点。在以后当我们比较不带缓存的I/O函数(chapter 3)以及标准I/O函数(chapter 5)时,还将看到这种差别。

进程控制系统调用(fork, exec和wait)通常由用户的应用程序直接调用(请回忆程序figure1.7中的基本shell)。但是为了简化某些常见的情况,UNIX系统也提供了一些库函数:例如system和popen。section8.13将说明system函数的一种使用基本的进程控制系统调用的实现。我们将在section 10.18强化这一实例以正确地处理信号。

为了定义大多数程序员应用的UNIX系统接口,我们不得不既说明系统调用和一些库函数。例如,如果我们只描述sbrk系统调用,那么就会忽略很多应用程序使用的malloc库函数。本书除了必须要区分两者时,对系统调用和库函数我们都将使用术语函数(function)来指代。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值