库函数与系统调用的区别

系统调用和库函数的关系 

系统调用通过 软中断int 0x80从用户态进入内核态 。 函数库中的某些函数调用了系统调用。 
函数库中的函数 可以没有调用系统调用,也可以调用多个系统调用 。 编程人员可以通过函数库调用系统调用。 
高级编程也可以直接采用int 0x80进入系统调用,而不必通过函数库作为中介。 如果是在核心编程,也可以通过int 0x80进入系统调用,此时不能使用函数库。因为函数库中的函数是内核访问不到的。  
2、从用户调用库函数到系统调用执行的流程。 
1) 假设用户调用ssize_t write (int fields, cont void *buff, size_t nbytes);库函数。
 2) 库函数会执行int 0x80中断。因为 中断使得进程从用户态进入内核态,所以 参数通过寄存器传送。 
3) 0x80中断对应的中断例程被称为system call handler。
其工作是:
 i.  存储大多数寄存器到内核堆栈中。这是汇编代码写的。 
 ii.  执行真正的系统调用函数――system call service routine。这是C代码。  
 iii. 通过ret_from_sys_call ()返回,回到用户态的库函数。这是汇编代码。


 1、系统调用 

系统调用 提供的函数如open, close, read, write, ioctl等,需包含头文件 unistd.h。以write为例:其函数原型为 size_t write(int fd, const void *buf, size_t nbytes),其操作对象为 文件描述符或文件句柄fd(file descriptor),要想写一个文件,必须先以可写权限用open系统调用打开一个文件,获得所打开文件的fd,例如 fd=open(/"/dev/video/", O_RDWR)。fd是一个整型值,每新打开一个文件,所获得的fd为当前最大fd加1。Linux系统默认分配了3个文件描述符值:
0-standard input,1-standard output,2-standard error。
 系统调用通常用于底层文件访问(low-level file access),例如在驱动程序中对设备文件的直接访问。 
系统调用是操作系统相关的,因此一般没有跨操作系统的可移植性。 
系统调用发生在 内核空间,因此如果在用户空间的 一般应用程序中使用系统调用来进行文件操作,会有用户空间到内核空间切换的开销。事实上,即使在用户空间使用库函数来对文件进行操作,因为文件总是存在于存储介质上,因此 不管是读写操作,都是对硬件(存储器)的操作,都必然会引起系统调用。也就是说, 库函数对文件的操作实际上是通过系统调用来实现的。例如C库函数fwrite()就是通过write()系统调用来实现的。 

这样的话,使用库函数也有系统调用的开销,为什么不直接使用系统调用呢?这是因为,读写文件通常是大量的数据(这种大量是相对于底层驱动的系统调用所实现的数据操作单位而言),这时,使用库函数就可以大大减少系统调用的次数。这一结果又 缘于缓冲区技术。在 用户空间和内核空间,对文件操作都使用了缓冲区,例如用fwrite写文件,都是 先将内容写到用户空间缓冲区,当用户空间缓冲区满或者写操作结束时,才将用户缓冲区的内容写到内核缓冲区,同样的道理,当内核缓冲区满或写结束时才将 内核缓冲区内容写到文件对应的硬件媒介。 

2、库函数调用 

标准C库函数提供的文件操作函数如fopen, fread, fwrite, fclose, fflush, fseek等,需包含头文件stdio.h。以fwrite为例,其函数原型为size_t fwrite(const void *buffer, size_t size, size_t item_num, FILE *pf),其操作对象为文件指针FILE *pf,要想写一个文件,必须先以可写权限用fopen函数打开一个文件,获得所打开文件的FILE结构指针pf,例如pf=fopen(/"~/proj/filename/", /"w/")。实际上,由于库函数对文件的操作最终是通过系统调用实现的,因此, 每打开一个文件所获得的FILE结构指针都有一个内核空间的文件描述符fd与之对应。同样有相应的预定义的FILE指针:stdin-standard input,stdout-standard output,stderr-standard error。 库函数调用通常用于应用程序中对一般文件的访问。  库函数调用是系统无关的,因此可移植性好。 由于库函数调用是基于C库的,因此也就不可能用于内核空间的驱动程序中对设备的操作

你可能感兴趣的:(库函数与系统调用的区别)