`
weiyinchao88
  • 浏览: 1188414 次
文章分类
社区版块
存档分类
最新评论

linux内核的文件描述

 
阅读更多

我们在进程中要怎样去描述一个文件呢?我们用目录项(dentry)和索引节点(inode)。它们的定义如下:

struct dentry {
struct inode *d_inode; /* Where the name belongs to - NULL is
struct dentry *d_parent; /* parent directory */
struct list_head d_child; /* child of parent list */
struct dentry_operations*d_op;
struct super_block*d_sb; /* The root of the dentry tree */
void *d_fsdata; /* fs-specific data */
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
......
};
struct inode {
unsigned longi_ino;
atomic_ti_count;
umode_t i_mode;
unsigned inti_nlink;
uid_t i_uid;
gid_t i_gid;
dev_t i_rdev;
loff_t i_size;
struct timespeci_atime;
unsigned longi_blocks;
unsigned shorti_bytes;
unsigned char _sock;
12
struct inode_operations *i_op;
struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct super_block *i_sb;
......
};

所谓"文件", 就是按一定的形式存储在介质上的信息,所以一个文件其实包含了两方面的信息,一是存储的数据本身,二是有关该文件的组织和管理的信息。在内存中, 每个文件都有一个dentry(目录项)和inode(索引节点)结构,dentry记录着文件名,上级目录等信息,正是它形成了我们所看到的树状结构;而有关该文件的组织和管理的信息主要存放inode里面,它记录着文件在存储介质上的位置与分布。同时dentry->d_inode指向相应的inode结构。dentry与inode是多对一的关系,因为有可能一个文件有好几个文件名(硬链接, hard link, 可以参考这个网页 http://www.ugrad.cs.ubc.ca/~cs219/CourseNotes/Unix/commands-links.html)。

所有的dentry用d_parent和d_child连接起来,就形成了我们熟悉的树状结构。

inode代表的是物理意义上的文件,通过inode可以得到一个数组,这个数组记录了文件内容的位置,如该文件位于硬盘的第3,8,10块,那么这个数组的内容就是3,8,10。其索引节点号inode->i_ino,在同一个文件系统中是唯一的,内核只要根据i_ino,就可以计算出它对应的inode在介质上的位置。就硬盘来说,根据i_ino就可以计算出它对应的inode属于哪个块(block),从而找到相应的inode结构。但仅仅用inode还是无法描述出所有的文件系统,对于某一种特定的文件系统而言,比如ext3,在内存中用ext3_inode_info描述。他是一个包含inode的"容器"。

struct ext3_inode_info {
__le32 i_data[15];
......
struct inode vfs_inode;
};

le32 i data[15]这个数组就是上一段中所提到的那个数组。

注意,在遥远的2.4的古代,不同文件系统索引节点的内存映像(ext3_inode_info,reiserfs_inode_info,msdos_inode_info ...)都是用一个union内嵌在inode数据结构中的. 但inode作为一种非常基本的数据结构而言,这样搞太大了,不利于快速的分配和回收。但是后来发明了container_of(...)这种方法后,就把union移到了外部,我们可以用类似container of(inode, struct ext3_inode_info, vfs_inode),从inode出发,得到其的"容器"。

dentry和inode终究都是在内存中的,它们的原始信息必须要有一个载体。否则断电之后岂不是玩完了?且听我慢慢道来。

文件可以分为磁盘文件,设备文件,和特殊文件三种。设备文件暂且不表。

磁盘文件
就磁盘文件而言,dentry和inode的载体在存储介质(磁盘)上。对于像ext3这样的磁盘文件来说,存储介质中的目录项和索引节点载体如下,
struct ext3_inode {
__le16 i_mode; /* File mode */
__le16 i_uid; /* Low 16 bits of Owner Uid */
__le32 i_size; /* Size in bytes */
__le32 i_atime; /* Access time */
__le32 i_ctime; /* Creation time */
__le32 i_mtime; /* Modification time */

__le32 i_dtime; /* Deletion Time */
__le16 i_gid; /* Low 16 bits of Group Id */
__le16 i_links_count; /* Links count */
......
__le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
......
}
struct ext3_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT3_NAME_LEN]; /* File name */
};

le32 i block[EXT2 N BLOCKS];/* Pointers to blocks */
i_block数组指示了文件的内容所存放的地点(在硬盘上的位置)。

ext3_inode是放在索引节点区,而ext3_dir_entry_2是以文件内容的形式存放在数据区。我们只要知道了ino,由于ext3_inode大小已知,我们就可以计算出ext3_inode在索引节点区的位置( ino * sizeof(ext3_inode) ),而得到了ext3_inode,我们根据i_block就可以知道这个文件的数据存放的地点。将磁盘上ext3_inode的内容读入到ext3_inode_info中的函数是ext3_read_inode()。以一个有100 block的硬盘为例,一个文件系统的组织布局大致如下图。位图区中的每一位表示每一个相应的对象有没有被使用。

特殊文件
特殊文件在内存中有inode和dentry数据结构,但是不一定在存储介质上有"索引节点",它断电之后的确就玩完了,所以不需要什么载体。当从一个特殊文件读时,所读出的数据是由系统内部按一定的规则临时生成的,或从内存中收集,加工出来的。sysfs里面就是典型的特殊文件。它存储的信息都是由系统动态的生成的,它动态的包含了整个机器的硬件资源情况。从sysfs读写就相当于向kobject层次结构提取数据。

还请注意, 我们谈到目录项和索引节点时,有两种含义。一种是在存储介质(硬盘)中的(如ext3_inode),一种是在内存中的,后者是根据在前者生成的。内存中的表示就是dentry和inode,它是VFS中的一层,不管什么样的文件系统,最后在内存中描述它的都是dentry和inode结构。我们使用不同的文件系统,就是将它们各自的文件信息都抽象到dentry和inode中去。这样对于高层来说,我们就可以不关心底层的实现,我们使用的都是一系列标准的函数调用。这就是VFS的精髓,实际上就是面向对象。

我们在进程中打开一个文件F,实际上就是要在内存中建立F的dentry,和inode结构,并让它们与进程结构联系来,把VFS中定义的接口给接起来。我们来看一看这个经典的图。这张图之于文件系统,就像每天爱你多一些之于张学友,番茄炒蛋之于复旦南区食堂,刻骨铭心。

分享到:
评论

相关推荐

    《深入分析Linux内核源代码》

    《深入分析Linux内核源代码》 第一章 走进Linux 第二章 Linux运行的硬件基础 第三章 中断机制 第四章 进程描述 第五章 进程调度与切换 第六章 Linux 内存管理 第七章 进程间通信 第八章 虚拟文件系统 第九章 Ext2 ...

    深入分析Linux内核源码.chm

    1.3走进Linux内核 1.4 分析Linux内核的意义 1.5 Linux内核结构 1.6 Linux内核源代码 1.7 Linux内核源代码分析工具 第二章 Linux运行的硬件基础 2.1 i386的寄存器 2.2 内存地址 2.3 段机制和描述符 2.4 分页机制 2.5 ...

    Linux内核中的文件描述符.docx

    Linux内核中的文件描述符.docx

    Linux内核 内容很全

    文件系统 77 7.1 第二个扩展文件系统EXT2 78 7.1.1 EXT2系统的inode节点 79 7.1.2 EXT2系统的超级块 80 7.1.3 EXT2系统的组描述符 80 7.1.4 EXT2系统的目录 81 7.1.5 在EXT2文件系统中查找文件 ...

    Linux内核Makefile文件

    Linux内核Makefile文件,详细描述了linux kernel的编译过程

    Linux2.6内核标准教程(共计8-- 第1个)

    Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先讲解Linux系统的引导过程;然后对Linux内核的3大核心模块——内存管理、进程管理、中断和异常处理进行了深入的分析; 在此基础上,...

    深入分析Linux内核源码

    深入分析Linux内核源码 前言 第一章 走进linux 1.1 GNU与Linux的成长 1.2 Linux的开发模式和运作机制 1.3走进Linux内核 1.3.1 Linux内核的特征 1.3.2 Linux内核版本的变化 1.4 分析Linux内核的意义 ...

    Linux编程--Linux内核

    Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 1.1.5 地址空间 9 1.1.6 时钟 9 1.2 软件基础 9 1.2.1 计算机语言 9 1.2.2 什么是操作...

    linux内核0.11代码,其中含有我的使用TC的描述文件

    linux内核0.11代码,其中含有我的使用TC的描述文件,TC的描述是对文件外部信息进行描述的,也是一种学习方法,欢迎提出意见

    Linux编写内核模块新增系统调用遍历进程树--基于Ubuntu20.04.03LTS实现

    实验目标:在Linux内核中增加一个系统调用,并编写对应的linux应用程序。利用该系统调用能够遍历系统当前所有进程的任务描述符,并按进程父子关系将这些描述符所对应的进程id(PID)组织成树形结构显示。 实验环境:...

    Linux2.6内核标准教程(共计8--第6个)

    Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先讲解Linux系统的引导过程;然后对Linux内核的3大核心模块——内存管理、进程管理、中断和异常处理进行了深入的分析; 在此基础上,...

    Linux2.6内核标准教程(共计8--第8个)

    Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先讲解Linux系统的引导过程;然后对Linux内核的3大核心模块——内存管理、进程管理、中断和异常处理进行了深入的分析; 在此基础上,...

    SONiC项目的Linux内核驱动程序_Makefile_Shell_下载

    SONiC - 内核\n描述\n此存储库包含为 SONiC 构建内核的脚本和补丁。SONiC 对所有平台使用相同的内核。我们更喜欢树外内核平台模块。我们在以下条件下接受内核补丁:\n需要启用现有的内核模块。\n现有的内核模块需要...

    Linux2.6内核标准教程(共计8--第3个)

    Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先讲解Linux系统的引导过程;然后对Linux内核的3大核心模块——内存管理、进程管理、中断和异常处理进行了深入的分析; 在此基础上,...

    Linux2.6内核标准教程(共计8--第7个)

    Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先讲解Linux系统的引导过程;然后对Linux内核的3大核心模块——内存管理、进程管理、中断和异常处理进行了深入的分析; 在此基础上,...

    深入分析linux内核源码

    第四章 进程描述 第五章进程调度 第六章 Linux内存管理 第七章 进程间通信 第八章 虚拟文件系统 第九章 Ext2文件系统 第十章 模块机制 第十一章 设备驱动程序 第十二章 网络 第十三章 启动系统

    为Linux内核增加一个系统调用.zip

    在 Linux 内核中增加一个系统调用,并编写对应的 Linux 应用程序。利用该系统调用能够遍历系统当前 所有进程的任务描述符,并按进程父子关系将这些描述符所对应的进程 id(PID)组织成树形结构显示。 整个程序的构思...

    Netlink实现Linux内核与用户空间通信

    Linux内核与用户空间通信的方式目前主要有9种,分别是内核启动参数、模块参数与 sysfs、sysctl、系统调用、netlink、procfs、seq_file、debugfs和relayfs。Netlink是一种特殊的文件描述符(套结字),为2.6.14及更高...

    Linux 内核实验室 - 基于 Docker 的极速 Linux 内核学习、开发和测试环境.rar

    本项目致力于创建一个基于 Docker + QEMU 的 Linux 实验环境,方便大家学习、开发和测试 Linux 内核。 Linux Lab 是一个开源软件,不提供任何保证,请自行承担使用过程中的任何风险。 项目功能 现在,Linux Lab 已经...

Global site tag (gtag.js) - Google Analytics