一、什么是文件描述符

在Linux下一切皆文件,对于内核而言,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数,当打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,使用open或creat返回文件描述符标示该文件,将其作为参数传送给read或write。

在linux中,进程是通过文件描述符(file descriptors 简称fd)来访问文件的,文件描述符实际上是一个整数。在程序刚启动的时候,默认有三个文件描述符,分别是:0(代表标准输入),1(代表标准输出),2(代表标准错误)。再打开一个新的文件的话,它的文件描述符就是3。

文件描述符的变化范围是0~OPEN_MAX-1.

二、如何创建文件描述符

进程获取文件描述符最常见的方法就是通过系统函数open或create获取,或者是从父进程继承。
从父进程继承的话,子进程就可以访问父进程所使用的文件。我们再深入想想,进程是独立运行的,互不干扰,如果父子进程要通信的话,是不是就可以通过这些都能访问的文件入手。

文件描述符对于每一个进程是唯一的,每个进程都有一张文件描述符表,用于管理文件描述符。当使用fork创建子进程的话,子进程会获得父进程所有文件描述符的副本,这些文件描述符在执行fork时打开。在由fcntl、dup和dup2子例程复制或拷贝某个进程时,会发生同样的复制过程。

三、文件描述符与打开文件之间的关系

每一个文件描述符都与一个打开的文件相对应,同时,不同的文件描述符也会指向同一个文件。相同的文件可以被不同的进程打开,也可以在同一个进程中被打开多次。系统为每一个进程维护了一个文件描述符表,该表的值从0开始,所以在不同的进程中会看到相同的文件描述符,这种情况下的相同的文件描述符有可能指向同一个文件,也有可能指向不同的文件。
内核维护了三种文件描述符表:
1、进程级别的文件描述符表
进程级别的文件描述符表的每一条目都记录了单个文件描述符的相关信息。表里面的信息分别是:控制文件描述符操作的一组标志、对打开文件句柄的引用。这个进程级别的文件描述符表用files_struct结构表示,在PCB中有一个这个结构类型的指针变量files。
files_struct定义如下:

struct files_struct {atomic_t count; /* 共享该表的进程数 */rwlock_t file_lock; /* 保护以下的所有域,以免在tsk->alloc_lock中的嵌套*/int max_fds; /*当前文件对象的最大数*/int max_fdset; /*当前文件描述符的最大数*/int next_fd; /*已分配的文件描述符加1*/struct file ** fd; /* 指向文件对象指针数组的指针 */fd_set *close_on_exec; /*指向执行exec( )时需要关闭的文件描述符*/fd_set *open_fds; /*指向打开文件描述符的指针*/fd_set close_on_exec_init;/* 执行exec( )时需要关闭的文件描述符的初 值集合*/fd_set open_fds_init; /*文件描述符的初值集合*/struct file * fd_array[32];/* 文件对象指针的初始化数组*/
};

2、系统级别的文件描述符表
内核对所有打开的文件有一个系统级别的文件描述符表。有时也称为打开文件描述符表,并将表格中各条目称为打开文件句柄。一个打开文件句柄存储了这个打开文件的全部相关信息。
大致包含以下信息:

  1. 当前文件偏移量
  2. 打开文件时所使用的状态标识(open中的flags参数)
  3. 文件访问模式(只读,只写,读写模式)
  4. 与信号驱动相关的设置。
  5. 对该文件的i-node引用。
  6. 文件类型和访问权限。
  7. 一个指针、指向该文件所持有的锁列表。
  8. 文件的各种属性,包括文件大小及不同类型操作相关的时间戳。

相关定义:

struct file
{struct list_head f_list; /*所有打开的文件形成一个链表*/struct dentry *f_dentry; /*指向相关目录项的指针*/struct vfsmount *f_vfsmnt; /*指向VFS安装点的指针*/struct file_operations *f_op; /*指向文件操作表的指针*/mode_t f_mode; /*文件的打开模式*/loff_t f_pos; /*文件的当前位置*/unsigned short f_flags; /*打开文件时所指定的标志*/unsigned short f_count; /*使用该结构的进程数*/unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;/*预读标志、要预读的最多页面数、上次预读后的文件指针、预读的字节数以及预读的页面数*/int f_owner; /* 通过信号进行异步I/O数据的传送*/unsigned int f_uid, f_gid; /*用户的UID和GID*/int f_error; /*网络写操作的错误码*/unsigned long f_version; /*版本号*/void *private_data; /* tty驱动程序所需 */
};

3、文件系统的i-node表
保存了文件系统的相关信息。
内核中用inode结构表示具体的文件,而用file结构表示打开的文件描述符。
Linux2.6.27内核中,inode结构体具体定义如下:

struct inode {struct hlist_node    i_hash;struct list_head    i_list;struct list_head    i_sb_list;struct list_head    i_dentry;unsigned long        i_ino;atomic_t        i_count;unsigned int        i_nlink;uid_t            i_uid;gid_t            i_gid;dev_t            i_rdev;   //该成员表示设备文件的inode结构,它包含了真正的设备编号。u64            i_version;loff_t            i_size;#ifdef __NEED_I_SIZE_ORDEREDseqcount_t        i_size_seqcount;
}

它们之间的关系(节选自网络):

四、文件描述符的分配

文件描述符的分配:当用户调用相关函数比如open, creat等函数时,如果成功,会返回一个文件描述符,返回的文件描述符一定是当前进程最小没有用到的描述符。但是要特别注意文件描述符的最大值,可以通过命令$ulimit –n查看文件描述符的最大值,一般linux发行版都是1024,当然这个值可以修改的,具体可以参考关于文件描述符。

五、基于文件描述符的输入输出函数

接下来讲讲基于文件描述符的输入输出函数:

open:打开一个文件,并指定访问该文件的方式,调用成功后返回一个文件描述符。

creat:打开一个文件,如果该文件不存在,则创建它,调用成功后返回一个文件描述符。

close:关闭文件,进程对文件所加的锁全都被释放。

read:从文件描述符对应的文件中读取数据,调用成功后返回读出的字节数。

write:向文件描述符对应的文件中写入数据,调用成功后返回写入的字节数。

ftruncate:把文件描述符对应的文件缩短到指定的长度,调用成功后返回0。

lseek:在文件描述符对应的文件里把文件指针设定到指定的位置,调用成功后返回新指针的位置。

fsync:将所有已写入文件中的数据真正写到磁盘或其他下层设备上,调用成功后返回0。

fstat:返回文件描述符对应的文件的相关信息,把结果保存在struct stat中,调用成功后返回0。

fchown:改变与打开文件相关联的所有者和所有组,调用成功后返回0。

fchmod:把文件描述符对应的文件的权限位改为指定的八进制模式,调用成功后返回0。

flock:用于向文件描述符对应的文件施加建议性锁,调用成功后返回0。

fcntl:既能施加建议性锁也能施加强制性锁,能建立记录锁、读取锁和写入锁,调用成功后返回0。

dup:复制文件描述符,返回没使用的文件描述符中最小的编号。

dup2:由用户指定返回的文件描述符的值,用来重新打开或重定向一个文件描述符。

select:同时从多个文件描述符读取数据或向多个文件描述符写入数据。

1. dup:

  • 函数原型:int dup(int filefd)
  • 函数功能:复制一份现存的文件描述符filefd

2. dup2:

  • 函数原型:int dup2(int Oldfilefd, int Newfield)
  • 函数功能:复制一份现存的文件描述Oldfilefd,若Newfield等于Oldfilefd时,返回Newfield;若两者不相等时,若Newfield已经打开,先关闭Newfield,然后返回Newfield。

3. fcntl:

  • 函数原型:int fcntl (int filefd, int cmd, …)
  • 函数功能:fcntl有5种功能,通过第二个参数cmd来决定。这里只讲一种:复制一份现存的文件描述符,cmd为F_DUPFD。

由上面三个函数的功能都是复制文件描述符,记住是文件描述符,不是复制文件表,更不是复制节点表。

六、文件描述符与文件指针的区别

  • 文件描述符:在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。
  • 文件指针:C语言中使用文件指针做为I/O的句柄。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括一个缓冲区和一个文件描述符。而文件描述符是文件描述符表的一个索引,因此从某种意义上说文件指针就是句柄的句柄(在Windows系统上,文件描述符被称作文件句柄)。

原文链接:https://blog.csdn.net/lizhidefengzi/article/details/71481195

linux存储--文件描述符以及file结构体(一)相关推荐

  1. OS / Linux / 文件描述符以及 file 结构体

    零.前言 程序可以理解为硬盘上的普通二进制文件:进程是加载到内存中的二进制文件,除了加载到内存中的二进制文件外,还附有所有对于该二进制文件描述信息的结构体,描述该进程的结构体叫PCB(进程控制块),在 ...

  2. linux存储--文件描述符fd与FILE结构体(二)

    文件描述符fd 对于linux而言,所有对设备(对于linux而言,一切皆文件)和文件的操作都使用文件描述符来进行的. 文件描述符是一个非负的整数,它是一个索引值,指向内核中每个进程打开文件的记录表. ...

  3. linux 文件指针,Linux中文件描述符fd与文件指针FILE*互相转换实例解析

    本文研究的主要是Linux中文件描述符fd与文件指针FILE*互相转换的相关内容,具体介绍如下. 1.文件描述符fd的定义:文件描述符在形式上是一个非负整数.实际上,它是一个索引值,指向内核为每一个进 ...

  4. linux中文件描述符fd和文件指针flip的理解

    整理自:http://www.cnblogs.com/Jezze/archive/2011/12/23/2299861.html 简单归纳:fd(file descriptor)只是一个整数,在ope ...

  5. 深入理解Linux/Unix文件描述符和epoll

    Linux/Unix 文件描述符(File Describer)的本质 Linux/Unix(以下简称Linux)系统中,每个进程都有一个专用的数组,数组的元素是一个结构体,称为文件描述符File D ...

  6. ftpclient读取服务器文件能获得文件名文件大小0_理解Linux的文件描述符FD与Inode

    FD 文件描述符 一.概念 Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被 ...

  7. 文件句柄(file handles) 文件描述符(file descriptors)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  8. Linux:文件描述符

    1. 概述 在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录文件.链接文件和设备文件.文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是 ...

  9. Linux进程描述符task struct结构体详解--Linux进程的管理与调度(一)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 日期 内 ...

最新文章

  1. H3C Boot升级 Serial模式
  2. Opencv获取导入DNN模型的各层信息
  3. 解除svn控制下的文件夹的svn的控制
  4. H5js的一些好玩的东西
  5. poj 1218(经典开关问题,模拟)
  6. OpenCASCADE:Foundation Classes简介
  7. Effective Java之消除受检警告(二十四)
  8. 全国python一级考试_全国青少年软件编程(python)等级考试试卷(一级)
  9. 错误-trustAnchors参数必须为非空
  10. pythonmysql数据分析_利用Mysql进行python的数据分析
  11. 【转载】Deferred Shading
  12. 关于Lazarus下PowerPDF控件的使用
  13. 将2010年的旧电脑升级为Win8.1遇到的问题及解决办法
  14. Java实现动态sin和cos函数图像
  15. 数据库索引的填充因子
  16. elment中走马灯与满屏图片实现
  17. 广西行政村数据shp_广西自治区乡镇行政区划数据 精度1:10万
  18. uni-app保存图片到本地相册
  19. 全球及中国塑料机械行业十四五发展战略与竞争格局展望报告2022版
  20. MySQL使用cmd输入show databases没有反应

热门文章

  1. python的翻译-Python编写简单的谷歌翻译软件
  2. python手机版下载3.7.2-qpython手机版下载
  3. python语法基础知识-python基础必学的语法知识
  4. python培训班深圳-深圳哪里有Python培训班?
  5. 中国最大的python社区-python中的最小最大算法
  6. 财务大数据比赛有python吗-大数据工作内容有哪些?老男孩Python数据培训
  7. python怎么把数据写入txt-python(如何将数据写入本地txt文本文件)
  8. python基础常用语句-Python语言的一些基本常用语句
  9. python发声-python写报警程序中的声音实现winsound
  10. Ubuntu16.04 Linux上比较好用的截图工具Flameshot