文件描述符(File Descriptor)

一、介绍

内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。

二、功能

文件描述符

文件描述符(File Descriptor)是一个整型,可以理解为一个指向文件的指针。需要注意的就是,一个进程在结束的时候会关闭所有打开的文件描述符,但是0,1,2除外。0,1,2,分别代表标准输入流,标准输出流和标准错误流。这3个文件描述符是由kernel打开和进行管理的,不需要我们来打开和关闭。

文件描述符表

每个表项包含一个指向已打开的文件的指针,如下图所示

  • 每个进程的文件描述符表是一个数组,数组的索引是文件描述符(fd),数组的值是指向 文件表 中某个条目的指针。

  • 文件表是内核维护的全局数据结构,包含文件的打开模式、读写位置等信息。


当调用open打开一个文件或创建一个新文件时,内核分配一个文件描述符并返回给用户程序,该文件描述符表项中的指针指向新打开的文件。当读写文件时,用户程序把文件描述符传给read或write,内核根据文件描述符找到相应的表项,再通过表项中的指针找到相应的文件。

我们知道,程序启动时会自动打开三个文件:标准输入、标准输出和标准错误输出。在C标准库中
分别用FILE *指针stdin、 stdout和stderr表示。这三个文件的描述符分别是0、 1、 2,保存在相应
的FILE结构体中。这3个文件描述符是由kernel打开和进行管理的,不需要我们来打开和关闭。

头文件unistd.h中有如下的宏定义来表示这三个文件描述符:

 

三、文件描述符的创建

文件描述符是通过系统调用创建的,常见的系统调用包括:

  • open():打开文件,返回文件描述符。

  • socket():创建套接字,返回文件描述符。

  • pipe():创建管道,返回两个文件描述符(一个用于读,一个用于写)。

  • dup()dup2():复制文件描述符。

示例:使用 open() 创建文件描述符

四. 文件描述符的复制

  • dup():复制一个文件描述符,返回一个新的文件描述符。

  • dup2():复制一个文件描述符,并指定新的文件描述符编号。

示例:使用 dup2() 重定向标准输出

五. 文件描述符的关闭

  • 使用 close() 系统调用关闭文件描述符。

  • 关闭文件描述符会释放相关资源,并将其从文件描述符表中移除。

示例:关闭文件描述符

六. 文件描述符的限制

  • 每个进程的文件描述符数量是有限制的。

可以通过以下命令查看当前系统的文件描述符限制:

  • ulimit -n

  • 可以通过修改 /etc/security/limits.conf 或使用 ulimit 命令调整限制。

七. 文件描述符与 I/O 多路复用

在 Linux 中,文件描述符是 I/O 多路复用(如 selectpollepoll)的基础。这些机制允许程序同时监控多个文件描述符的状态。

示例:使用 select 监控文件描述符

八. 文件描述符与进程间通信

文件描述符在进程间通信(IPC)中扮演重要角色,例如:

  • 管道(pipe):通过 pipe() 创建两个文件描述符,一个用于读,一个用于写。

  • 套接字(socket):通过 socket() 创建文件描述符,用于网络通信。

示例:使用管道进行进程间通信

九. 文件描述符的高级用法

  • fcntl():用于控制文件描述符的属性,例如设置非阻塞模式。

  • ioctl():用于设备文件的控制操作。

  • sendfile():高效地在文件描述符之间传输数据。

示例:使用 fcntl() 设置非阻塞模式

十、总结

文件描述符是 Linux 中管理文件和 I/O 操作的核心概念。通过文件描述符,程序可以访问文件、管道、套接字等资源。理解文件描述符的工作原理对于编写高效的 Linux 程序至关重要。

 

 

参考:

文件描述符(File Descriptor)简介-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值