从实现着的角度来看,系统调用和库函数之间有根本的区别,但从用户的角度来看,其区别并不重要。系统调用和库函数都以C函数的形式出现,两者都是为应用程序提供服务。
什么是系统调用和库函数?
系统调用
系统调用(system call)是操作系统内核提供的函数,在内核态运行(kernel mode),是操作系统为用户提供的一些接口。它通过软中断向内核态发出一个明确的请求。有一些任务需要进程跑在内核态才能执行,比如和硬件打交道。所以进程调用系统调用就能让自己运行在内核态从而执行这些类似的任务。
例如,printf()需要调用write()系统调用来完成输出。
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("hello,worldn");
return 0;
}
实际上是调用的write()来实现的,而这个write()就是系统提供的接口函数。
在Linux man命令,用来查看系统中自带的各种参考手册。
1 Executable programs or shell commands
2 System calls (functions provided by the kernel)
3 Library calls (functions wiroutinesthin program libraries)
4 Special files (usually found in /dev)
5 File formats and conventions eg /etc/passwd
6 Games
7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)
8 System administration commands (usually only for root)
9 Kernel routines [Non standard]
翻译:
1、可执行程序或者shell命令
2、系统调用(内核可以调用的函数,运行在核心态,内核空间,系统核心可直接呼叫的函数与工具等,通过这个,可以很方便的查到调用某个函数,需要加什么头文件,例如open,write函数)
3、库函数(运行在用户态,用户空间,一些常用的函数与函数库,大部分为c的函数库,例如print,fread)
4、特殊设备(一般是/dev下的各种设备,例如硬盘设备,光盘等)
5、文件格式(说明这个文件中的各个字段的含义,例如/etc/passwd)
6、游戏(保留给游戏使用,由各个游戏自己定义)
7、杂项,例如Linux文件系统,网络协议等,变量说明等
8、系统管路员命令(只有管理员才能使用的命令,例如ifconfig,reboot等)
9、跟kernel内核有关的文件
而通过 man 2 和查看系统调用。
man 2 write
man 用法请查看这一篇Linux 如何查看帮助信息
那么系统调用的意义是什么?
提高系统安全性
系统调用是内核代码,内核代码能访问系统上的所有地址空间,而我们执行的代码是用户空间的代码,用户空间的代码在对系统进行操作时是有限制的,(作为一个新手程序员,系统如果不对你写的代码进行限制,万一把系统搞蹦了呢)。因此系统调用的另一个功能就是维护了系统的安全性,你要用就直接调用我这个接口就行了,不用你自己写。
常见系统调用
open, close, read, write, ioctl,fork,clone,exit,
getpid,access,chdir,chmod,stat,brk,mmap等
需要包含unistd.h等头文件。
库函数
库函数是高层的,是在系统调用上的一层包装,运行在用户态(user mode),为程序员提供调用真正的在幕后完成实际事务的系统调用的更为方便的接口。 比如一些字符串处理函数(strcmp,strlen)等。
库函数类型
可分为两类:没有调用系统调用,以及调用了系统调用。
有一些库函数没有调用系统调用,比如strlen。有一些则会调用,比如库函数fopen内部调用了open系统调用。
常见库函数
printf,scanf,fopen,fclose,fgetc,fgets,fprintf,fsacnf,fputc,
calloc,free,malloc,realloc,strcat,strchr,strcmp,strcpy,strlen,strstr等
需要包含stdio.h,string.h,alloc.h,stdlib.h等头文件。
应用程序可以调用系统调用或库函数,同时我们还应注意到许多库函数也涉及了系统调用,它们之间的关系如下图:
上图显示了应用程序可以同时和库函数或者系统调用交互。同样的,一个库函数内部也可以再调用系统调用。但是,只有系统调用有权限访问硬件。
系统调用和库函数的区别
系统调用通常不可替换,而库函数通常可替换
普通的库函数调用由函数库或用户自己提供,因此库函数是可以替换的。例如,对于存储空间分配函数malloc,如果不习惯它的操作方式,我们完全可以定义自己的malloc函数。
不要误解认为malloc是系统系统,这是错的。因为malloc只是个库函数,内部是使用brk或者sbrk系统调用来实现内部分配。
系统调用运行在内核空间,而库函数运行在用户空间
因为系统调用属于内核,和库函数不属于内核。因此,如果当用户态进程调用一个系统调用时,CPU需要将其切换到内核态,并执行一个内核函数。
传统的方式是引发“int $0x8o”中断。内核捕获中断后,会把运行态从用户态切换到内核态。
一些其他的区别
1、库函数可以很方便的调试;而系统调用很麻烦因为运行在内核。
2、一个库函数执行时间是计算用户层次时间(user level time);但是系统调用的运行时间是作为系统时间来计算的;
总结
系统调用是为了方便应用程序使用操作系统的接口,而库函数是为了方便人们编写应用程序而引出的。
我们应当认识到,系统调用是我们无法更改的一种特征,如果我们愿意可以替换库函数,但是却不能替换系统调用。