文章参考:文件描述符的本质文件描述符和文件指针的区别文件描述符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. 查看Linux端口的占用及连接情况

    [root@cloudplatform ~]# netstat -nap | grep 22066 | grep 127.0.0.1 -vtcp        0      0 :::22066    ...

  2. vijos 1128 N个数选K个数 (DFS )

    从 n 个整数中任选 k 个整数相加,可分别得到一系列的和 要求你计算出和为素数共有多少种 IN4 33 7 12 19 OUT1 # include <iostream> # inclu ...

  3. AndroidStudio将html5打包成apk

    我想将html5的动画效果打包成手机app,以方便传播.而在android开发的组件中就直接由webview可以访问网页,另外在android工程中,assets文件夹下的内容是不会在被编译的,因此可 ...

  4. C# Winform将控件作为参数传递

    最近做个Winform 的程序设计,需要将窗体的控件作为参数传递到另外一个类的函数中去使用,每次都会忘记,简单的记下来,以备即时查看. 1. 设置控件的modifier属性设置为public 2. 以 ...

  5. P1541 乌龟棋 线性dp

    题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行NN个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第NN格是终点,游戏要求玩家控制一个乌龟棋子 ...

  6. Arbitrage HDU1217

    汇率转换问题: 怎么样才能套利 可以用Floyd算法: #include<bits/stdc++.h> using namespace std; ][]; int main() { int ...

  7. 【Java】 剑指offer(66) 构建乘积数组

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 给定一个数组A[0, 1, …, n-1],请构建一个数组B[ ...

  8. SSL/TLS中间人攻击

    准备:kali.xp kali ip:192.168.14.157 目标ip:192.168.14.158 目标网关:192.168.14.2 使用工具:ettercap.sslstrip.arpsp ...

  9. Python爬虫之PyQuery使用(六)

    Python爬虫之PyQuery使用 PyQuery简介 pyquery能够通过选择器精确定位 DOM 树中的目标并进行操作.pyquery相当于jQuery的python实现,可以用于解析HTML网 ...

  10. MySQL 5.7.14 net start mysql 服务无法启动

    解决方法: 1.mysqld  --initialize 初始化data目录 2.重新输入net start mysql命令 补充,服务停止的方法:net stop mysql