文章参考:文件描述符的本质文件描述符和文件指针的区别文件描述符fd和文件指针flip的理解

推荐:task_struct 和文件系统的关系

系统中文件相关表

  右侧的表称为i节点表,在整个系统中只有1张。该表可以视为结构体数组,该数组的一个元素对应于一个物理文件。

  中间的表称为文件表,在整个系统中只有1张。该表可以视为结构体数组,一个结构体中有很多字段,其中有3个字段比较重要:

    file status flags:用于记录文件被打开来读的,还是写的。其实记录的就是open调用中用户指定的第2个参数
    current file offset:用于记录文件的当前读写位置(指针)。正是由于此字段的存在,使得一个文件被打开并读取后,下一次读取将从上一次读取的字符后开始读取
    v-node ptr:该字段是指针,指向右侧表的一个元素,从而关联了物理文件。

  左侧的表称为文件描述符表,每个进程有且仅有1张。该表可以视为指针数组,数组的元素指向文件表的一个元素。最重要的是:数组元素的下标就是大名鼎鼎的文件描述符,数组元素的值就是指向 File 结构体的指针

系统调用时的操作

  文件描述符的操作函数 open, 返回一个文件描述符,内核会在每个进程空间中维护一个文件描述符表,所有打开的文件都将通过此表中的文件描述符来引用。

    新建一个i节点表元素,让其对应打开的物理文件(如果对应于该物理文件的i节点元素已经建立,就不做任何操作);

    新建一个文件表的元素,根据open的第2个参数设置file status flags字段,将current file offset字段置0,将v-node ptr指向刚建立的i节点表元素;

    在文件描述符表中,寻找1个尚未使用的元素,在该元素中填入一个指针值,让其指向刚建立的文件表元素。最重要的是:将该元素的下标作为open的返回值返回。

  文件描述符的操作函数 read(write,)根据传入的文件描述符,OS就可以找到对应的文件描述符表元素,进而找到文件表的元素,进而找到i节点表元素,从而完成对物理文件的读写。

  而流操作函数 fopen, 返回的是一个FILE结构指针,FILE结构是包含有文件描述符的,FILE结构函数可以看作是对fd直接操作的系统调用的封装,它的优点是带有I/O缓存。

文件描述符和文件指针的概念一总

  文件描述符:在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。即已打开的文件在内核中用 File 结构体表示,文件描述符表中的指针指向 File 结构体。优点是兼容POSIX标准,许多系统调用都依赖于它;缺点是不能移植到unix之外的系统上去。

  文件指针:C语言中使用文件指针而不是文件描述符做为I/O的句柄。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构主要包括一个I/O缓冲区和一个文件描述符。而文件描述符是文件描述符表中的一个索引,因此从某种意义上说文件指针就是句柄的句柄(在Windows系统上,文件描述符被称作文件句柄)。相当于在上图中最左侧又虚拟出一个 struct File,其中 struct 中有个元素是文件描述符,指向进程表项中的 fd 索引(自己的理解,不知道正不正确)。文件指针的优点是C语言中的通用格式,便于移植。

  既然FILE结构中含有文件描述符,那么可以使用fopen来获得文件指针,然后从文件指针获取文件描述符,文件描述符应该是唯一的,而文件指针却不是唯一的,但指向的对象是唯一的

进程与文件描述符

  内核会在每个进程空间中维护一个文件描述符表, 所有打开的文件都将通过此表中的文件描述符来引用; 而流(如: fopen)返回的是一个FILE结构指针, FILE结构是包含有文件描述符的,FILE结构函数可以看作是对fd直接操作的系统调用的封装, 它的优点是带有I/O 缓存。

  每个进程在PCB(Process Control Block)即进程控制块中都保存着一份文件描述符表,文件描述符就是这个表的索引,文件描述表中每个表项都有一个指向已打开文件的指针,现在我们明确一下:已打开的文件在内核中用 FILE 结构体表示,文件描述符表中的指针指向 FILE 结构体。

fork 对文件描述符的影响

  fork会导致子进程继承父进程打开的文件描述符,其本质是将父进程的整个文件描述符表复制一份,放到子进程的PCB中。因此父、子进程中相同文件描述符(文件描述符为整数)指向的是同一个文件表元素,这将导致父(子)进程读取文件后,子(父)进程将读取同一文件的后续内容。所以在创建守护进程时,都使用 close 关闭掉从父进程继承的文件描述符。

FILE的结构

struct _iobuf {
  char *_ptr; //缓冲区当前指针
  int _cnt; //文件的引用计数
  char *_base; //缓冲区基址
  int _flag; //文件读写模式
  int _file; //文件描述符
  int _charbuf; //缓冲区剩余自己个数
  int _bufsiz; //缓冲区大小
  char *_tmpfname;
};
typedef struct _iobuf FILE;

open和fopen的区别

  open:返回一个文件描述符,无缓冲,与 write、read 配合使用

  fopen:返回 File *,有缓冲,与 fwrite、fread 配合使用

Linux-文件描述符的本质及与文件指针的区别的更多相关文章

  1. Linux 利用进程打开的文件描述符(/proc)恢复被误删文件

    Linux 利用进程打开的文件描述符(/proc)恢复被误删文件 在 windows 上删除文件时,如果文件还在使用中,会提示一个错误:但是在 linux 上删除文件时,无论文件是否在使用中,甚至是还 ...

  2. 文件指针/句柄(FILE*)、文件描述符(fd)以及 文件路径(filepath)的相互转换(转)

    转自: http://blog.csdn.net/jenghau/article/details/5532265 文件指针/句柄(FILE*).文件描述符(fd)以及 文件路径(filepath)的相 ...

  3. linux文件描述符open file descriptors与open files的区别

    一个文件被打开,也可能没有文件描述符,比如current working diretories,memory mapped files and executable text files ;losf可 ...

  4. linux专题一之文件描述符、重定向、管道符、tee命令

    本节讨论一下几个问题: 1. 文件描述符. 2. 重定向. 3. 管道符 4. tee的用法. 1. 文件描述符. 在linux系统中一切皆文件.文件夹和设备都是文件.如何用来区别不同的文件呢?这里的 ...

  5. Linux文件描述符与打开文件之间的区别(转载)

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/38965239   1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为: ...

  6. linux文件描述符--转载

    转自:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录 ...

  7. Linux中的文件描述符与打开文件之间的关系

    Linux中的文件描述符与打开文件之间的关系 导读 内核(kernel)利用文件描述符(file descriptor)来访问文件.文件描述符是非负整数.打开现存文件或新建文件时,内核会返回一个文件描 ...

  8. Linux中的文件描述符与打开文件之间的关系------------每天进步一点点系列

    http://blog.csdn.net/cywosp/article/details/38965239 1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录文件. ...

  9. (转)Linux中的文件描述符

    本文转自:http://blog.csdn.net/cywosp/article/details/38965239 作者:cywosp 1. 概述 在Linux系统中一切皆可以看成是文件,文件又可分为 ...

随机推荐

  1. JQuery中jsCharts图表插件(十)

    一:1.jsCharts图表插件 注意:从官方下来的例子都没指定页面编码,在这种情况下,浏览器就会使用默认设置中文编码:GB2312,GBK等:导致无法执行. 请在html代码中的<head&g ...

  2. Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架

    Asp.Net Core 2.0 项目实战(1) NCMVC开源下载了 Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架 Asp.Ne ...

  3. moodle 笔记

    默认版块的设置: //这些变量为新课程定义了DEFAULT块变量如果设置了这个变量,它将覆盖所有其他变量,并且是唯一使用的变量s $CFG->defaultblocks_override = ' ...

  4. Mac配置Eclipse CDT的Debug出现的问题(转)

      问题1:出现 Could not determine GDB version using command: gdb --version 原因: mac上没有安装gdb或者gdb位置配置有问题 解决 ...

  5. Python爬虫之requests+正则表达式抓取猫眼电影top100以及瓜子二手网二手车信息(四)

    requests+正则表达式抓取猫眼电影top100 一.首先我们先分析下网页结构 可以看到第一页的URL和第二页的URL的区别在于offset的值,第一页为0,第二页为10,以此类推. 二.< ...

  6. C#多线程编程实战(二):线程同步

    2.1 简介 竞争条件:多个线程同时使用共享对象.需要同步这些线程使得共享对象的操作能够以正确的顺序执行 线程同步问题:多线程的执行并没有正确的同步,当一个线程执行递增和递减操作时,其他线程需要依次等 ...

  7. POJ 2417 Discrete Logging BSGS

    http://poj.org/problem?id=2417 BSGS 大步小步法( baby step giant step ) sqrt( p )的复杂度求出 ( a^x ) % p = b % ...

  8. 洛谷.3803.[模板]多项式乘法(FFT)

    题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. 5.4 又看了一遍,这个也不错. 2019.3.7 叕看了一遍,推荐这个. #inclu ...

  9. pwcrack--一款集合多种md5解密的工具

    项目开源地址:https://github.com/L-codes/pwcrack-framework Ruby2.5+ (tested with Ruby2.5.3 & Ruby 2.6.3 ...

  10. 公开课 之 tony 电子时钟 (课堂笔记)

    # tony 之电子时钟from PyQt5.QtWidgets import QApplication, QWidget, QLCDNumber, QDesktopWidget, QVBoxLayo ...