[Linux C]系统调用(system call)和库函数调用(Library functions)
Linux 下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions)。系统调用实际上就是指最底层的一个调用,在 linux 程序设计里面就是底层 调用的意思。面向的是硬件。而库函数调用则面向的是应用开发的,相当于应用程序的 api, 采用这样的方式有很多种原因,
第一:双缓冲技术的实现。第二,可移植性。第三,底层调用本身的一些性能方面的缺陷。
第四:让 api 也可以有了级别和专门的工作面向。
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 库的,因此也就不可能用于内核空间的驱动程序中对设备的操作。

[Linux C]系统调用(system call)和库函数调用(Library functions)的更多相关文章
- linux内核系统调用和标准C库函数的关系分析
http://blog.csdn.net/skyflying2012/article/details/10044343
- Linux系统调用和库函数调用的区别
Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意思 ...
- linux系统调用和库函数调用的区别(转)
Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).可以参考<Linux程序设计>(英文原版为<Beginning ...
- [转载]Linux下关于system调用
曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入.只是简单的知道用这个函数执行一个系统命令,这远远不够,它的返回值.它所执行命令的返回值以及命令执行失败原 ...
- Linux 下系统调用的三种方法
系统调用(System Call)是操作系统为在用户态运行的进程与硬件设备(如CPU.磁盘.打印机等)进行交互提供的一组接口.当用户进程需要发生系统调用时,CPU 通过软中断切换到内核态开始执行内核系 ...
- Linux添加系统调用的两种方法
前言 系统调用的基本原理 系统调用其实就是函数调用,只不过调用的是内核态的函数,但是我们知道,用户态是不能随意调用内核态的函数的,所以采用软中断的方式从用户态陷入到内核态.在内核中通过软中断0X80, ...
- 系统调用system call以及strace/dtruss
计算机系统的各种硬件资源是有限的,在现代多任务操作系统上同时运行的多个进程都需要访问这些资源,进程是不允许直接操作这些资源的,所有对这些资源的访问都必须有操作系统控制.也就是说操作系统是使用这些资源的 ...
- 深入理解Linux的系统调用【转】
一. 什么是系统调用 在Linux的世界里,我们经常会遇到系统调用这一术语,所谓系统调用,就是内核提供的.功能十分强大的一系列的函数.这些系统调用是在内核中实现的,再通过一定的方式把系统调用给用户,一 ...
- 【原创】Linux 增加系统调用
Linux 增加系统调用大致步骤: 1.下载好内核文件,在内核源文件中添加好自己的调用函数. 2.编译内核 3.验证. 一.在内核源文件中增加自己的函数 首先将内核文件移至/usr/src/下并解 ...
随机推荐
- struct timeval和gettimeofday
struct timeval和gettimeofday() struct timeval结构体在time.h中的定义为: struct timeval { time_t tv_sec; /* Seco ...
- vue中使用base64进行加解密
vue进行Base64加解密 背景 项目中需要对特殊字符进行处理,避免json和数据库的特殊字符(""等)冲突,刚好学了信息安全,干脆整个加解密,wkk.. 使用步骤 打开dos, ...
- qt4.7.0 交叉编译环境搭建经验总结
一.前期软件准备: 1 .虚拟机fedora9.到fedora官网下载,地址 http://fedoraproject.org/ 版本推荐使用fedora9,在vm内安装,并且不安装vmware ...
- Ubuntu安装Docker 适合Ubuntu17.04版本
Docker介绍 Docker是一个开源的容器引擎,它有助于更快地交付产品.Docker可将应用程序和基础设施层隔离,并且将基础设施当作程序一样进行管理.使用Docker,可以更快地打包,测试以及部署 ...
- Cocos2d-x碰撞检測
假设不适用Box2D物理引擎.那么要进行Cocos2d-x的碰撞检測那我们的方法往往就是进行"矩形和点"."矩形和矩形"这样粗略的碰撞检測.我们一般採取开启sc ...
- 每天自己主动备份mysql脚本
定时运行脚本: 1.运行 crontab -e 00 00 * * * /bin/bash yourpath/mysqlbak.sh 2.打开自己主动运行文件 vi /etc/crontab 在etc ...
- 三种数据库日期转字符串对照sql server、oracle、mysql(V4.11)
三种数据库日期转换对照: http://blog.csdn.net/zljjava/article/details/17552741 SQL类型转换函数:cast(type1 as type2) 数据 ...
- 2014.08.04,读书,读书笔记-《Matlab概率与数理统计分析》-第1章 MATLAB的数据基础
第1章 MATLAB数据基础 虽然一直间或使用MATLAB,但从来没有系统的学习过,现在开始也不晚.先对几个重点或者平时忽略的要点做下笔记. %后的所有文字为注释,多条命令可以放在一行,但要用逗号或分 ...
- vue-quill-editor 禁止编辑
每天学习一点点,知识财富涨点点 因为权限问题需要对富文本vue-quill-editor进行禁止编辑,因为也不是专业前端,处理起问题来还是只有看文档和百度,发现对这个提问不是很多,可能很多大牛都不会出 ...
- python一行代码实现9x9乘法表
for i in range(1,10): for j in range(1,i+1): print('%s * %s = %s ' %(i,j,i*j),end="") prin ...