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);

相关文章
|
7月前
|
C语言
C语言进阶——文件的读写(文件使用方式、文件的顺序读写、常用函数、fprintf、fscanf)
C语言进阶——文件的读写(文件使用方式、文件的顺序读写、常用函数、fprintf、fscanf)
55 0
|
8月前
|
存储 程序员 Linux
6.C语言:用fopen函数关闭数据文件
6.C语言:用fopen函数关闭数据文件
116 1
|
8月前
|
存储 缓存 Unix
C语言第四章(进程间的通信,管道通信,pipe()函数)
C语言第四章(进程间的通信,管道通信,pipe()函数)
344 0
|
8月前
|
Unix Linux API
Linux文件描述符和文件指针互转
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。FILE *指针变量标识符;其中FILE应为大写,它实际上是由系统定义的一个结构,该结构中含有文件名、文件状态和文件当前位置等信息。在编写源程序时不必关心FILE结构的细节。
74 0
|
缓存 Linux API
系统编程之文件IO(七)——0,1,2三个文件描述符与库函数和系统调用的区别
系统编程之文件IO(七)——0,1,2三个文件描述符与库函数和系统调用的区别
115 0
系统编程之文件IO(七)——0,1,2三个文件描述符与库函数和系统调用的区别
|
C语言 C++ 索引
用C语言读取大文件的问题 内存映射
在处理一般的文件(文本/非文本),这些足够了。然而在处理比较大的文件如几十M, 几百M, 甚至上G的文件, 这时再用一般手段处理,系统就显的力不从心了要把文件读出,再写进,耗费的是CPU利用率与内存以及IO的频繁操作。这显然是令用户难以忍受的为了解决这个吃内存,占CPU,以及IO瓶颈,windows核心编程提供了内存映射文件技术(Maping File)
C#编程-110:文件操作File静态类
C#编程-110:文件操作File静态类
136 0
C#编程-110:文件操作File静态类
|
C语言
【C 语言】文件操作 ( 按照内存块的方式读写文件 | fread 函数 | fwrite 函数 )
【C 语言】文件操作 ( 按照内存块的方式读写文件 | fread 函数 | fwrite 函数 )
241 0
【C 语言】文件操作 ( 按照内存块的方式读写文件 | fread 函数 | fwrite 函数 )
|
C语言
【C 语言】文件操作 ( fseek 函数 )
【C 语言】文件操作 ( fseek 函数 )
253 0
【C 语言】文件操作 ( fseek 函数 )
|
存储 C语言
【C 语言】文件操作 ( 按照文本行的方式读写文件 | fgets 函数 | fputs 函数 )
【C 语言】文件操作 ( 按照文本行的方式读写文件 | fgets 函数 | fputs 函数 )
270 0
【C 语言】文件操作 ( 按照文本行的方式读写文件 | fgets 函数 | fputs 函数 )