FILE* 和文件描述符及其相互转换【系统编程】

简介: FILE* 和文件描述符及其相互转换【系统编程】


FILE*(文件指针)

  每个被使用的文件都会在内存中开辟一个相应的文件信息区,用来存储文件的相关信息(包含文件的名字,文件状态及文件当前的位置等)。这些信息被集合在一个结构体中,这个结构体也叫做FILE。

  可以看到FILE结构体里面有很多的属性。

  一般我们都是使用一个FILE的指针来维护一个文件,这样用起来会方便许多。

  通过文件指针变量就能够找到与之相关联的文件信息:

文件描述符

  开始之前先来介绍使用系统接口open来打开一个文件的流程:open -> 从PCB也就是task_struct中找到files指针 -> file指针指向结构体files_struct -> files_struct中有一个重要的部分是fd_array[]数组,里面包含一个file指针 -> 通过这个file指针就可以指向一个file结构体 -> 这个file结构体中含有文件的所以信息,于是就找到了相应的文件。文件描述符就是fd_array[]数组的下标,所以文件描述符是从0开始的。只要拿着文件描述符就能找到对应的文件。

为什么这么繁琐呢?

  这是降低了进程管理和文件管理的耦合度,使得进程管理这块,我们拿着文件描述符就能找到对应的文件,不用管文件管理的事。

0 & 1& 1

  • Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2.
  • 0,1,2对应的物理设备一般是:键盘,显示器,显示器
  • 所以当我们还需要打开其他文件的时候,一般都是从3开始向后分配的。

文件描述符的分配规则

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> 
int main()
{
  int fd = open("F:\\比特就业课\\t.txt", O_WRONLY);
  printf("%d", fd);
  return 0;
}

  不出所料,分配的文件描述符就是3。

  当我们关闭0号文件描述符后:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> 
int main()
{
  close(0);
  int fd = open("F:\\比特就业课\\t.txt", O_WRONLY);
  printf("%d", fd);
  return 0;
}

  由此可以得到结论:文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。

文件描述符和FILE的联系

FILE是一个struct结构体,有C标准库提供,C文件库函数内部一定会调用系统调用,所以使用FILE,实际内部使用的是fd,在系统的角度上来看,FILE和fd,只认fd。

FILE结构体里面一定会存在一个属性是文件描述符,当使用FILE是就能通过文件描述符找到底层的file结构体,获取文件信息。

FILE和文件描述符的相互转换:

FILE* --> fd :

#inlcude <stdio.h>

int fileno(FILE *stream);

fd --> FILE* :

#include <stdio.h>

FILE *fdopen(int fd, const char *mode);

相关文章
|
存储 Cloud Native Linux
C++ vector元素类型为什么不能是引用
C++ vector元素类型为什么不能是引用
|
安全 Linux
【Linux】阻塞信号|信号原理
本教程从信号的基本概念入手,逐步讲解了阻塞信号的实现方法及其应用场景。通过对这些技术的掌握,您可以更好地控制进程在处理信号时的行为,确保应用程序在复杂的多任务环境中正常运行。
437 84
|
存储 Java API
Java数据结构之ArrayList(如果想知道Java中有关ArrayList的知识点,那么只看这一篇就足够了!)
Java数据结构之ArrayList(如果想知道Java中有关ArrayList的知识点,那么只看这一篇就足够了!)
Java数据结构之ArrayList(如果想知道Java中有关ArrayList的知识点,那么只看这一篇就足够了!)
|
XML 开发工具 Android开发
Repo工作原理及常用命令总结——2023.07(下)
Repo工作原理及常用命令总结——2023.07(下)
3478 0
|
前端开发 JavaScript
JavaScript新纪元:ES6+特性深度解析与实战应用
【10月更文挑战第29天】本文深入解析ES6+的核心特性,包括箭头函数、模板字符串、解构赋值、Promise、模块化和类等,结合实战应用,展示如何利用这些新特性编写更加高效和优雅的代码。
458 0
|
传感器 芯片
嵌入式通信协议全解析:SPI、I²C、UART详解(附带面试题)
通信是指人与人或人与自然之间通过某种行为或媒介进行的信息交流与传递。从广义上来说,通信是指需要信息的双方或多方在不违背各自意愿的情况下采用任意方法、任意媒质,将信息从某方准确安全地传送到另方。在出现电波传递通信后,通信被单一解释为信息的传递,是指由一地向另一地进行信息的传输与交换,其目的是传输消息。通信方式包括利用“电”来传递消息的电信,这种通信具有迅速、准确、可靠等特点,且几乎不受时间、地点、空间、距离的限制,因而得到了飞速发展和广泛应用。
6486 0
|
存储 监控 物联网
MQTT协议问题之OTA升级包下载如何解决
MQTT协议是一个轻量级的消息传输协议,设计用于物联网(IoT)环境中设备间的通信;本合集将详细阐述MQTT协议的基本原理、特性以及各种实际应用场景,供用户学习和参考。
759 3
|
数据挖掘 C++
C++中的科学计数法
C++中的科学计数法
2737 0
|
前端开发 开发者 UED
一文搞懂css中精灵图如何使用
一文搞懂css中精灵图如何使用
一文搞懂css中精灵图如何使用
|
数据可视化 算法 数据挖掘
聚类分析 | MATLAB实现基于DBSCAD密度聚类算法可视化
聚类分析 | MATLAB实现基于DBSCAD密度聚类算法可视化