在Linux系统中,内核为用户程序提供了两方面的支持。其一是系统调用接口,另一方面是通过开发环境库函数或内核库函数与内核进行信息交流。不过内核库函数仅供内核创建的任务0和任务1使用,它们最终还是去调用系统调用。
系统调用主要提供给系统软件编程或者用于库函数的实现。而一般用户开发的程序则是通过调用像libc等库函数来访问内核资源。这些库中的函数或资源通常被称为应用程序编程接口(API),其中定义了应用程序使用的一组标准编程接口。通过调用这些库中的程序,应用程序代码能够完成各种常用工作,例如,打开和关闭对文件或设备的访问、进行科学计算、出错处理以及访问组和用户标识号ID等系统信息。
API与系统调用的区别在于:为了实现某一应用程序接口标准,例如POSIX,其中的API可以与一个系统调用对应,也可能由几个系统调用的功能共同实现。当然某些API函数可能根本就不需要使用系统调用,即不使用内核功能。因此函数库可以看做实现像POSIX标准的主体界面,应用程序不用管它与系统调用之间到底存在什么关系。无论一个操作系统提供的系统调用有多么大的区别,但只要它遵循同一个API标准,那么应用程序就可以在这些操作系统之间具有可移植性。
系统调用是内核与外界接口的最高层。在内核中,每个系统调用都有一个序列号(在include/unistd.h头文件中定义),并且常以宏的形式实现。应用程序不应该直接使用系统调用,因为这样的话,程序的移植性就不好了。因此目前Linux标准库(Linux Standard Base,LSB)和许多其他标准都不允许应用程序直接访问系统调用宏。
库函数一般包括C语言没有提供的执行高级功能的用户级函数,如输入/输出和字符串处理函数。某些库函数只是系统调用的增强功能版。例如,标准I/O库函数fopen和fclose提供了与系统调用open和close类似的功能,不过是在更高的层次上。在这种情况下,系统调用通常能提供比库函数略微好一些的性能,但是库函数却能提供更多的功能,而且更具检错能力。