文件系统(十二)—伪文件系统

前文中我们已经分析了文件系统,而文件系统的精髓所在是让用户可以通过文件描述符来对指定的inode进行一系列的操作。

本章开始学习伪文件系统,伪文件系统和普通文件系统的区别在于,其inode对用户不可访问,即仅在内核态可见,从用户层的视角来看该文件系统并不存在。伪文件系统的作用是对一些操作系统中的元素进行封装,和普通的文件统一接口,如块设备bdevfs,管道文件pipefs,套接字socketfs等。通过这种方式的统一封装,才实现了Linux一切皆文件的思想。如下图中红色的都应该算是伪文件系统,本章就学习其中的procfs/sysfs/pipefs。

在这里插入图片描述

1 proc文件系统

1.1 数据结构

proc文件系统由proc_dir_entry结构体实例组成,内核各子系统可通过接口函数向proc文件系统添加目录和文件。proc_dir_entry结构体定义在fs/proc/internal.h头文件

在这里插入图片描述

在VFS中proc文件系统节点由proc_inode结构体表示,其定义在fs/proc/internal.h
在这里插入图片描述

1.2 初始化

内核在启动函数start_kernel()中调用proc_root_init()函数完成proc文件系统的初始化工作,函数定义在/fs/proc/root.c文件内,代码如下:
在这里插入图片描述

proc_root_init()函数的主要工作是创建proc_inode结构体slab缓存,注册proc_fs_type文件系统类型,为各子系统添加目录项和文件。

在这里插入图片描述

proc文件系统需要挂载到根文件系统(通常是/proc挂载点),才能对用户进程可见。那么如何对proc文件系统的挂载,以及用户进程对proc文件系统中文件的操作。

在这里插入图片描述

1.3 挂载文件系统

proc文件系统类型挂载函数proc_mount()定义如下(fs/proc/root.c)

在这里插入图片描述

其与前面介绍过的文件系统挂载类似,主要是通过proc_fill_super填充超级块实例,创建设置denry、proc_inode实例等,主要来看看proc_fill_super函数实现(fs/proc/inode.c)

在这里插入图片描述

内核在/fs/proc/root.c文件内静态创建了proc文件系统根目录项的proc_dir_entry实例proc_root:

在这里插入图片描述

proc_fill_super()函数首先对super_block实例进行初始化,设置其超级块操作结构实例为proc_sops,然后调用proc_get_inode()函数创建proc_inode实例,并建立其与proc_root实例的关联,创建文件系统根目录项dentry实例,并关联proc_inode.vfs_inode成员(inode实例),最后在根目录下创建self和thread-self目录项。所以其数据结构如下图所示

在这里插入图片描述

proc文件系统需要由用户挂载,才能对用户可见。通常在操作系统启动脚本中会将proc文件系统挂载到/proc目录下。

  • 挂载操作将创建proc文件系统超级块super_block实例,文件系统根目录项dentry实例,以及proc_inode实例。proc_inode实例中包含节点inode结构体成员,其i_op、i_fop成员分别指向proc_root实例中proc_iops、proc_fops指向的实例。
  • 对于根节点,proc_iops、proc_fops指向的实例是专用的,它们分别为proc_root_inode_operations、proc_root_operations。
  • 用户打开proc文件系统中文件时,将为每个路径分量(目录项)创建dentry和proc_inode实例,并建立proc_inode实例与proc_dir_entry实例之间的关联。

1.4 添加普通目录项

向proc文件系统添加普通目录项的接口函数为proc_mkdir_data(),定义如下(fs/proc/generic.c)
在这里插入图片描述

设置普通目录文件的节点操作结构和文件操作结构实例为proc_dir_inode_operations和proc_dir_operations,这两个实例都是通用的实例,最后调用proc_register()函数注册proc_dir_entry实例,主要是将其添加到父目录项管理的红黑树中。

向proc文件系统添加文件的操作与添加普通目录项的操作类似,主要区别是添加文件时,需要定义文件操作结构file_operations实例,传递给proc_dir_entry实例。

在这里插入图片描述

对于普通目录项,proc_inode内嵌inode实例i_op和i_fop成员赋值为proc_dir_entry实例proc_iops、proc_fops成员值。对于文件目录项,proc_inode内嵌inode实例i_op赋值为proc_dir_entry实例proc_iops成员值,而i_fop成员指向proc_reg_file_ops实例,

在这里插入图片描述

1.6 打开文件

proc文件系统中路径搜索都是从其根目录项开始的,根目录项与普通目录项关联inode_operations实例不同,搜索函数也不同,如下图所示。

在这里插入图片描述

根目录项关联inode_operations实例定义如下(fs/proc/root.c):

在这里插入图片描述

普通目录项关联inode_operations实例定义如下(fs/proc/generic.c):

在这里插入图片描述

在打开文件的操作中将调用proc_get_inode()函数为proc_dir_entry实例创建proc_inode实例,如果实例代表的是普通文件,则inode实例关联的文件操作结构实例设为proc_reg_file_ops,定义如下:

在这里插入图片描述

打开文件后,需要读写文件,其也就可以调用该接口的read/write接口,其整个流程如下

在这里插入图片描述

2. sysfs

sys文件系统与proc文件系统一样,通过内核数据结构实例,组织成文件系统,它由kernfs_node结构体实例构成。

kernfs文件系统并不是一个完整的文件系统,它只是提供构建文件系统的基础组件及相关的接口函数,使用kernfs文件系统的子系统需要定义并注册文件系统类型file_system_type实例。其过程与procfs文件基本类似就不单独介绍。

3 pipefs

管道(pipe)和命名管道是进程间通信的机制,用于进程间的单向数据传输。管道和命名管道的两端分别是写进程和读进程,本质上是一种特殊的文件,文件的内容保存在一个内存的缓冲区中(FIFO)。

管道没有文件名称,由内核管理,只能用于同源的进程间(fork()出来的进程间)通信,对其它非同源的进程不可见。命名管道与普通文件一样具有文件名称,文件保存在具体文件系统中,导出到内核根文件系统,对用户可见,可用于任意进程之间的通信。

管道/命名管道包含一个缓存区,缓存区可认为有一个进口和一个出口,写进程从进口写入数据,读进程从出口读取数据,数据在缓存区中按写入时间先后顺序排列,先进的数据先读出,只能按顺序读取,不能任意读取。

在这里插入图片描述

父进程创建子进程后,表示管道的两个文件描述符将传递给子进程。如果父进程要通过管道向子进程传递数据,则关闭父进程读端文件描述符和子进程写端文件描述符。父进程则可以向管道写入数据,子进程可从管道读取数据。

pipefs伪文件系统类型pipe_fs_type实例定义如下(/fs/pipe.c)

在这里插入图片描述

pipefs伪文件系统初始化函数init_pipe_fs()中注册了文件系统类型,并执行了内核挂载,函数定义如下:

在这里插入图片描述

其pipefs_mount比较简单,主要工作是创建挂载mount结构体实例,调用文件系统类型中定义的mount()函数,创建超级块super_block、根目录项dentry和inode结构体实例,并建立以上数据结构实例之间的关系,执行结果如下图所示。
在这里插入图片描述

我们来学习下如何使用的管道,用户进程创建管道的系统调用为pipe和pipe2,实现如下

在这里插入图片描述

pipe2()系统调用实现函数定义如下:

在这里插入图片描述

pipe()/pipe2()系统调用将返回2个文件描述符,参数fildes指向的数组用于存放返回的文件描述符,fildes[0]表示读取端文件描述符(只读形式),fildes[1]表示写入端文件描述符(只写形式)。
在这里插入图片描述

系统调用内通过__do_pipe_flags()函数创建表示管道的dentry和inode实例,分配并初始化表示管道的pipe_inode_info结构体实例,分配2个file实例,2个文件描述符,2个file实例关联到同一个inode实例,file和inode关联的文件操作结构实例为pipefifo_fops
在这里插入图片描述

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Linux文件系统是指Linux内核提供的一种特殊的文件系统,其中最常见的是/proc目录下的procfs文件系统。它是一个在内存中存在的文件系统,不占用硬盘空间。通过procfs文件系统,用户可以查看系统硬件和当前正在运行的进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。此外,Linux内核还提供了其他文件系统,如sysfs和devfs,它们也以文件的形式向用户提供了访问系统内核数据的接口。通过这些数据接口,用户和应用程序可以获取系统的信息,并且内核也允许用户修改一些参数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Linux详解(内核和文件系统)](https://blog.csdn.net/weixin_44983653/article/details/94732559)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Linux文件系统](https://blog.csdn.net/PythonLife/article/details/114768584)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值