Linux C中库函数与系统调用的区别详细解析_unix linux

从程序完成的功能来看,函数库提供的函数通常是不需要操作系统的服务,函数是在用户空间内执行的,除非函数涉及到I/O操作等,一般是不会切到核心态的。系统调用是要求操作系统为用户提供进程,提供某种服务,通常是涉及系统的硬件资源和一些敏感的软件资源等。

函数库的函数,尤其与输入输出相关的函数,大多必须通过Linux的系统调用来完成。因此我们可以将函数库的函数当成应用程序设计人员与系统调用程序之间的一个中间层,通过这个中间层,我们可以用一致的接口来安全的调用系统调用。这样程序员可以只要写一次代码就能够在不同版本的linux系统间使用积压种具体实现完全不同的系统调用。至于如何实现对不同的系统调用的兼容性问题,那是函数库开发者所关心的问题。

从程序执行效率来看,系统调用的执行效率大多要比函数高,尤其是处理输入输出的函数。当处理的数据量比较小时,函数库的函数执行效率可能比较好,因为函数库的作法是将要处理的数据先存入缓冲区内,等到缓冲区装满了,再将数据一次写入或者读出。这种方式处理小量数据时效率比较高,但是在进行系统调用时,因为用户进程从用户模式进入系统核心模式,中间涉及了许多额外的任务的切换工作,这些操作称为上下文切换,此类的额外工作会影响系统的执行效率。但是当要处理的数据量比较大时,例如当输入输出的数据量超过文件系统定义的尽寸时,利用系统调用可获得较高的效率。

从程序的可移植性的角度来看,相对于系统调用,C语言的标准备函数库(ANSI C) 具备较高的可移植性,在不同的系统环境下,只要做很少的修改,通常情况是不需要修改的。

Linux C中库函数和系统调用的区别
库函数是高层的,完全运行在用户空间,为程序员提供调用真正的在幕后完成实际事务的系统调用的更方便的接口。系统调用在内核态运行并且由内核自己提供。标准C库函数printf()可以被看做是一个通用的输出语句,但它实际做的是将数据转化为符合格式的字符串并且调用系统调用 write()输出这些字符串。

是否想看一看printf()究竟使用了哪些系统调用? 这很容易,编译下面的代码。

复制代码 代码如下:

#include <stdio.h>
int main(void)
{ printf("hello"); return 0; } 

使用命令gcc -Wall -o hello hello.c编译。用命令 strace hello 跟踪该可执行文件。是否很惊讶? 每一行都和一个系统调用相对应。 strace是一个非常有用的程序,它可以告诉你程序使用了哪些系统调用和这些系统调用的参数,返回值。 这是一个极有价值的查看程序在干什么的工具。在输出的末尾,你应该看到这样类似的一行 write(1, "hello", 5hello)。这就是我们要找的。藏在面具printf() 的真实面目。既然绝大多数人使用库函数来对文件I/O进行操作(像 fopen, fputs, fclose)。 你可以查看man说明的第二部分使用命令man 2 write 。man说明的第二部分专门介绍系统调用(像kill()和read())。 man说明的第三部分则专门介绍你可能更熟悉的库函数(像cosh()和random())。

你甚至可以编写代码去覆盖系统调用,正如我们不久要做的。骇客常这样做来为系统安装后门或木马。 但你可以用它来完成一些更有益的事,像让内核在每次某人删除文件时输出 “ Tee hee, that tickles!” 的信息

时间: 2024-09-20 15:24:30

Linux C中库函数与系统调用的区别详细解析_unix linux的相关文章

linux 系统调用与标准库调用的区别详细解析_unix linux

1.系统调用和库函数的关系 系统调用通过软中断int 0x80从用户态进入内核态. 函数库中的某些函数调用了系统调用. 函数库中的函数可以没有调用系统调用,也可以调用多个系统调用. 编程人员可以通过函数库调用系统调用. 高级编程也可以直接采用int 0x80进入系统调用,而不必通过函数库作为中介. 如果是在核心编程,也可以通过int 0x80进入系统调用,此时不能使用函数库.因为函数库中的函数是内核访问不到的.  2.从用户调用库函数到系统调用执行的流程. 1) 假设用户调用ssize_t wr

js中opener与parent的区别详细解析

 本篇文章主要是对js中opener与parent的区别进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 opener即谁打开我的,比如A页面利用window.open弹出了B页面窗口,那么A页面所在窗口就是B页面的opener,在B页面通过opener对象可以访问A页面.   parent表示父窗口,比如一个A页面利用iframe或frame调用B页面,那么A页面所在窗口就是B页面的parent.在JS中,window.opener只是对弹出窗口的母窗口的一个引用.比如:a.ht

linux 内存管理机制详细解析_unix linux

物理内存和虚拟内存我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念. 物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space). 作为物理内存的扩展,linux会在物理内存不足时,使用交换分区的

C++标准库中sstream与strstream的区别详细解析_C 语言

在C++有两种字符串流,一种在sstream中定义,另一种在strstream中定义.它们实现的东西基本一样. strstream里包含class strstreambuf;class istrstream;class ostrstream;class strstream;它们是基于C类型字符串char*编写的 sstream中包含class istringstream;class ostringstream;class stringbuf;class stringstream;class --

linux中uptime命令的用法详细解析_unix linux

系统中的uptime命令主要用于获取主机运行时间和查询linux系统负载等信息.uptime命令可以显示系统已经运行了多长时间,信息显示依次为:现在时间.系统已经运行了多长时间.目前有多少登陆用户.系统在过去的1分钟.5分钟和15分钟内的平均负载. uptime命令用法十分简单:直接输入uptime即可.另外还有一个参数  -V ,是用来查询版本的. (注意是大写的字母v)[linux @ localhost]$ uptime –Vprocps version 3.2.7[linux @ loc

C++中overload,override,overwrite的区别详细解析_C 语言

Overload(重载):在C++程序中,可以将语义.功能相似的几个函数用同一个名字表示,但参数或返回值不同(包括类型.顺序不同),即函数重载.(1)相同的范围(在同一个类中):(2)函数名字相同:(3)参数不同:(4)virtual 关键字可有可无. Override(覆盖):是指派生类函数覆盖基类函数,特征是:(1)不同的范围(分别位于派生类与基类):(2)函数名字相同:(3)参数相同:(4)基类函数必须有virtual 关键字. Overwrite(重写):是指派生类的函数屏蔽了与其同名的

js中opener与parent的区别详细解析_javascript技巧

opener即谁打开我的,比如A页面利用window.open弹出了B页面窗口,那么A页面所在窗口就是B页面的opener,在B页面通过opener对象可以访问A页面. parent表示父窗口,比如一个A页面利用iframe或frame调用B页面,那么A页面所在窗口就是B页面的parent.在JS中,window.opener只是对弹出窗口的母窗口的一个引用.比如:a.html中,通过点击按钮等方式window.open出一个新的窗口b.html.那么在b.html中,就可以通过window.o

C++中继承与组合的区别详细解析_C 语言

C++的"继承"特性可以提高程序的可复用性.正因为"继承"太有用.太容易用,才要防止乱用"继承".我们要给"继承"立一些使用规则: 一.如果类A 和类B 毫不相关,不可以为了使B 的功能更多些而让B 继承A 的功能. 不要觉得"不吃白不吃",让一个好端端的健壮青年无缘无故地吃人参补身体. 二.如果类B 有必要使用A 的功能,则要分两种情况考虑: (1)若在逻辑上B 是A 的"一种"(a

java中sdk与jdk的区别详细解析_java

SDK是Software Development Kit的缩写,中文意思是"软件开发工具包".这是一个覆盖面相当广泛的名词,可以这么说:辅助开发某一类软件的相关文档.范例和工具的集合都可以叫做"SDK".SDK是一系列文件的组合,它为软件的开发提供一个平台(它为软件开发使用各种API提供便利). JDK(Java Development Kit,Java开发工具包)是Sun Microsystems针对Java开发员的产品.自从Java推出以来,JDK已经成为使用最