8 UNIX 系统接口
UNIX 操作系统通过一系列的系统调用提供服务
这些系统调用实际上是操作系统内的函数,它们可以被用户程序调用
本章将介绍如何在 C 语言程序中使用一些重要的系统调用
如果读者使用的是 UNIX,本章将会对你有直接的帮助
这是因为,我们经常需要借助于系统调用以获得最高的效率,或者访问标准库中没有的某些功能
但是,即使读者是在其它操作系统上使用 C 语言,本章的例子也将会帮助你对 C 语言程序设计有更深入的了解
不同系统中的代码具有相似性,只是一些细节上有区别而已
因为 ANSI C 标准函数库是以 UNIX 系统为基础建立起来的,所以,学习本章中的程序还将有助于更好地理解标准库
本章的内容包括 3 个主要部分,输入/输出、文件系统和存储分配
其中,前两部分的内容要求读者对 UNIX 系统的外部特性有一定的了解
第 7 章介绍的输入/输出接口对任何操作系统都是一样的
在任何特定的系统中,标准库函数的实现必须通过宿主系统提供的功能来实现
接下来的几节将介绍 UNIX 系统中用于输入和输出的系统调用,并介绍如何通过它们实现标准库
8.1 文件描述符
在 UNIX 操作系统中,所有的外围设备(包括键盘和显示器)都被看作是文件系统中的文件
因此,所有的输入/输出都要通过读文件或写文件完成
也就是说,通过一个单一的接口就可以处理外围设备和程序之间的所有通信
通常情况下,在读或写文件之前,必须先将这个意图通知系统,该过程称为打开文件
如果是写一个文件,则可能需要先创建该文件,也可能需要丢弃该文件中原先已存在的内容
系统检查你的权力(该文件是否存在?是否有访问它的权限?)
如果一切正常,操作系统将向程序返回一个小的非负整数,该整数称为文件描述符
任何时候对文件的输入/输出都是通过文件描述符标识文件,而不是通过文件名标识文件
文件描述符类似于标准库中的文件指针或 MS-DOS 中的文件句柄
系统负责维护已打开文件的所有信息,用户程序只能通过文件描述符引用文件
因为大多数的输入/输出是通过键盘和显示器来实现的,为了方便起见,UNIX 对此做了特别的安排
当命令解释程序(即 shell)运行一个程序的时候
将打开 3 个文件,对应的文件描述符分别为 0
、1
、2
,依次表示标准输入,标准输出和标准错误
如果程序从文件 0
中读,对 1
和 2
进行写,就可以进行输/输出而不必关心打开文件的问题
程序的使用者可通过 <
和 >
重定向程序的 I/O
:
prog <infile >outfile
这种情况下,shell 把文件描述符 0
和 1
的默认赋值改变为指定的文件
通常,文件描述符 2
仍与显示器相关联,这样,出错信息会输出到显示器上
与管道相关的输入/输出也有类似的特性
在任何情况下,文件赋值的改变都不是由程序完成的,而是由 shell 完成的
只要程序使用文件 0
作为输入,文件 1
和 2
作为输出,它就不会知道程序的输入从哪里来,并输出到哪里去