Linux 文件描述符及FILE结构体

本文详细介绍了Linux系统中文件描述符的概念及其作用机制,包括文件描述符的创建、使用及与文件指针的关系等,同时深入探讨了内核层面文件描述符的管理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

也就是说创建一个文件描述符应该是从启用最小的未被访问的位置进行,比如创建一个文件file1,那么如果file1运行的时候,他的文件描述符就是3

FILE结构体
就是file_stuct,文件描述符则是这个结构体的一个成员
也就是说文件指针指向一个FILE结构体,而此结构体中包含一个成员叫做文件描述符(fd),文件描述符是整数,fd是内核访问文件的桥梁,并且在C库中,f系列只认文件指针

那么对于内核而言,他是如何通过文件描述符来访问文件的呢,这里内核维护了三种文件描述符表:

文件描述符(进程级别)
进程级别的文件描述符表的每一条目都记录了单个文件描述符的相关信息。表里面的信息分别是:控制文件描述符操作的一组标志、对打开文件句柄的引用。这个进程级别的文件描述符表用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];/* 文件对象指针的初始化数组*/
};

文件描述符(系统级别)
内核对所有打开的文件有一个系统级别的文件描述符表。有时也称为打开文件描述符表,并将表格中各条目称为打开文件句柄。一个打开文件句柄存储了这个打开文件的全部相关信息。
大致包含以下信息:
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驱动程序所需 */

};

i-node表(系统级别)
保存了文件系统的相关信息。

struct inode──字符设备驱动相关的重要结构介绍
内核中用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_ORDERED
seqcount_t        i_size_seqcount;
}

那么这里的三种文件文件描述符之间有什么关系呢,其实看一看三种文件描述符的代码我们也可以看得出来。(以下图片选择网络,链接http://www.linuxprobe.com/linux-file-descriptor.html
这里写图片描述

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值