Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions)

可以参考《Linux程序设计》(英文原版为《Beginning Linux Programming》,作者是Neil Matthew和Richard Stones)第三章: Working with files。

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库的,因此也就不可能用于内核空间的驱动程序中对设备的操作

库函数是高层的,完全运行在用户空间,为程序员提供调用真正的在幕后完成实际事务的系统调用的更方便的接口。系统调用在内核态运行并且由内核自己提供。标准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!” 的信息。

linux系统调用和库函数调用相关推荐

  1. (转)Linux系统调用和库函数调用的区别

    Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions). 系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意 ...

  2. linux系统调用和库函数调用的区别

    1.系统调用 系统调用提供的函数如open, close, read, write, ioctl等,需包含头文件unistd.h.以write为例:其函数原型为 size_t write(int fd ...

  3. 转载 linux系统调用和库函数调用的区别

    源地址 http://blog.csdn.net/zhangskd/article/details/6956638 Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(L ...

  4. 系统调用和库函数调用的区别

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

  5. Unix——系统调用和库函数调用概念区别和联系

    Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意思 ...

  6. 系统调用和库函数调用

    借鉴https://blog.csdn.net/lf_2016/article/details/54587020 系统调用:用户直接调用操作系统暴露出来的接口,这种方式成为系统调用. 文件I/O操作就 ...

  7. linux系统调用及错误处理

    原文地址http://daileinote.com/computer/linux_sys/02 系统调用是内核提供给外部程序的接口,进程可以通过系统调用来一自己的名义来执行某些动作.在深入了解系统调用 ...

  8. linux系统调用过程

    在用户程序调用read.write等系统调用时,linux内核发生了哪些动作呢.下面以write为例: 调用write系统调用,进入C库执行write函数,就是产生了一个int 0X80的一个中断,这 ...

  9. 什么是Linux系统调用system call?(Linux内核中设置的一组用于实现各种系统功能的子程序)(区别于标准C库函数调用)核心态和用户态的概念、中断的概念、系统调用号、系统调用表

    文章目录 什么是系统调用? 为什么要用系统调用? 系统调用是怎么工作的? 如何使用系统调用? _syscall*()是什么? errno是什么? 调用性能问题 Linux系统调用列表 进程控制 文件系 ...

  10. 操作系统原理,系统调用,系统调用与库函数API等函数之间的调用关系,功能与机制设计,系统调用的执行过程与Linux系统调用执行示例,不同操作系统下的PCB

    操作系统原理,系统调用,功能与机制设计,系统调用的执行过程与Linux系统调用执行示例,不同操作系统下的PCB 一.系统调用:操作系统功能调用,用户在编程时可以调用的操作系统功能. 1.系统调用是操作 ...

最新文章

  1. 【Web安全】利用burp抓包和CSRF伪造进入admin真实后台
  2. js(三) ajax异步局部刷新技术底层代码实现
  3. CapsLock Enhancement via AutoHotKey
  4. 用公式实现动态设置图表的轴数据项
  5. mysql主从配置 简书_Mysql主从配置,实现读写分离-Go语言中文社区
  6. OpenCL的安装与配置
  7. asp.net cookie操作-添加cookie,添加键值,移除cookie,移除键值
  8. 以LeNet-5为例理解CNN
  9. 双亲委派机制_史上三次破坏ClassLoader双亲委派机制
  10. 小米12 Ultra或将在5月发布:依旧为骁龙8移动平台
  11. SpringCloud学习笔记015---Spring Boot集成RabbitMQ发送接收JSON
  12. 美团 Flink 大作业部署与状态稳定性优化实践
  13. 龙之谷服务器列表不显示,龙之谷服务器列表,龙之谷服务器列表弹不出来
  14. gcd算法以及exgcd
  15. 解决xshell SSH 连接远程ubuntu make menuconfig 退格键无法删除问题
  16. Chrome浏览器账号无法登陆
  17. spark读写clickhouse
  18. 彻底卸载Websphere
  19. 编译安装mysql5.5
  20. 谷歌股票“一拆二”实为夯实掌舵权

热门文章

  1. java中do_while求阶乘倒数和,下面的程序是用do_while语句计算10的阶乘。请在程序的......
  2. python ttk separator_Python3 tkinter基础 Menu add_cascade 多级菜单 add_separator 分割线
  3. struts html form提交加密,strutshtml:form标签有关问题  解决立即给分
  4. 蓝桥杯2020年第十一届C/C++国赛B组第二题-扩散
  5. Vite 配置项目别名-最新版
  6. .net core 与ELK(4)后台运行els可视化工具和Kibana
  7. java中vector,array,list,arraylist的区别
  8. Codeforces Round #499 (Div. 2) C. Fly(数学+思维模拟)
  9. WDA基础七:TABStrip
  10. angular js权威指南笔记