文件描述符fd与FILE结构体的理解

2017-05-11 23:56 阅读 839 次 评论 0 条

对于内核而言,所有打开的文件都是通过文件描述符引用的。内核( kernel)利用文件描述符(file descriptor)来访问文件,基于文件描述符的I/O操作兼容与POSIX标准,在UNIX、Linux系统调用中,大量的系统调用都是依赖于文件描述符的。

文件描述符

文件描述符(file descriptor):文件描述符在形式上是一个非负的整数,实际上,它是一个索引值,指向内核的每一个进程所维护的该进程打开该文件的记录表。当程序打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符。(一般只适用于UNIX、Linux)。

标准文件描述符:在Centos中,存在于/usr/include/unistd.h头文件中。

文件描述符的有效范围:是 0 到 OPEN_MAX。一般来说,每个进程最多可以打开 64 个文件(0 — 63)。对于 FreeBSD 5.2.1、Mac OS X 10.3 和 Solaris 9 来说,每个进程最多可以打开文件的多少取决于系统内存的大小,int 的大小,以及系统管理员设定的限制。

但是在实际实现中会做相应的处理,一般最大打开文件数为系统内存的10%(称为系统级别限制),查看系统级别的最大文件打开数可以使用一下命令:

但是,内核为了不让某一个进程消耗掉所有的文件资源,会对单个进程最大打开文件数做默认处理,称之为用户级别限制,默认值一般为1024,使用下列命令查看:

修改最大打开文件描述符的方法如下:(临时生效,关机后失效)

文件描述符的分配:当我们打开一个新文件时,其文件描述符从几开始呢,我们不妨测试一下:

我们发现文件描述符fd为3,这是因为程序在启动的时候,已经打开了标准输入0,标准输出1以及标准错误2。

但是,当我们关闭某一个标准文件描述符时,新打开的文件的文件描述符是从3开始还是占据空位呢?

关闭标准输入0后,此时新打开的文件描述符fd变成了0。

因此我们得到一个结论:文件描述符的分配是从0~n中最小未被使用的来做文件描述符。本质上是数组的下标,特定地址与特定文件之间的映射关系。

当我们关闭1(标准输出)时,本来要在屏幕上显示的文件内容,写到了代替1这个位置的文件中,这就是输出重定向,与此对应的还有输入重定向和追加重定向。

文件描述符与文件之间的映射关系如下图所示:

总结:每一个文件描述符会与一个打开文件相对应,同时,不同的文件描述符也会指向同一个文件。相同的文件可以被不同的进程打开也可以在同一个进程中被多次打开。系统为每一个进程维护了一个文件描述符表,该表的值都是从0开始的,所以在不同的进程中你会看到相同的文件描述符,这种情况下相同文件描述符有可能指向同一个文件,也有可能指向不同的文件。

FILE结构体

FILE结构体中最重要的两个成员变量:文件描述符fd和缓冲区的大小

在了解文件结构体之前,首先要搞清楚文件指针(FILE*)的作用,在C语言中使用文件指针作为I/O的句柄,文件指针指向进程用户区中的一个被称为FILE结构的数据结构(FILE结构体)。

进程打开一个文件的过程:

①进程通过系统调用open()来打开一个文件,实质上是获得一个文件描述符,以便于进程通过文件描述符来读写该文件。

②进程打开文件时,会为该文件创建一个file对象,并将一个指向该file对象的指针存入进程描述符表(进程描述符数组),进而确定了打开文件的文件描述符(数组下标)。

③open()系统调用是在内核里通过sys_open()实现的,sys_open()将创建文件的dentry、inode和file对象。

④创建file对象时,将file对象指向了所属文件系统的操作函数集file_operations,而该函数集又来自具体文件的i节点,于是虚拟文件系统就与实际文件系统的操作就衔接起来了。并在file_struct结构体的进程打开文件表fd_array[NR_OPEN_DEFAULT]中查找一个空闲表项(也就是此时数组中最小的未被占用的表项),然后返回该表项的下标(文件描述符)。

我们可以在C语言的库函数stdio.h头文件中查看FILE结构体的定义:

files_struct结构体定义:描述符数组存放在进程打开的文件表files_struct结构中,文件描述符数组中存放了一个进程所打开的所有文件。

file结构体:

几个重要的成员变量:

f_flags:表示打开文件的权限 。
f_pos:表示当前读写文件的位置。
f_count:表示打开文件的引用计数,如果有多个文件指针指向它,就会增加f_count的值。
f_mode:设置对文件的访问模式,例如:只读,只写、可读可写等。

file_operations结构体:

总结

文件描述符(file_struct)是操作系统用来管理文件的数据结构,当我们创建一个进程时,会创建文件描述符表,进程控制块PCB中的fs指针指向文件描述符表。当我们创建文件时,会为指向该文件的指针FILE*关联一个文件描述符添加在文件描述符表中。在文件描述符表中fd相当与数组的索引,FILE*相当于数组的内容,指向一个文件结构体。

版权声明:本文著作权归原作者所有,欢迎分享本文,谢谢支持!
转载请注明:文件描述符fd与FILE结构体的理解 | 术与道的分享
分类:操作系统 标签:,
1024do.com导航_术与道导航平台

发表评论


表情