文件系统---代码层次深入分析文件系统

2023-11-17

    文件系统对用户来说,最重要的就是创建目录、创建文件、打开文件 和 文件读写。

    对通常的硬盘文件系统来说,涉及硬盘的读写和硬盘空间管理,从读写文件系统层一直到通用设备层再到硬盘驱动。为了简化,我们给出最简单文件系统,通过这个例子导入文件系统的概念。通过代码分析,逐层深入内核,了解架构:


1、简单的文件系统aufs

        这个文件系统直接创建在内存中,在内存中 

#include <linux/module.h> 
#include <linux/fs.h> 
#include <linux/pagemap.h> 
#include <linux/mount.h> 
#include <linux/init.h> 
#include <linux/namei.h> 

#define AUFS_MAGIC  0x64668735  

static struct vfsmount *aufs_mount;  
static int aufs_mount_count;  

static struct inode *aufs_get_inode(struct super_block *sb, int mode, dev_t dev)  
{  
  struct inode *inode = new_inode(sb);  

  if (inode) {  
       inode->i_mode = mode;  
       inode->i_uid = current->fsuid;  
       inode->i_gid = current->fsgid;  
       inode->i_blksize = PAGE_CACHE_SIZE;  
       inode->i_blocks = 0;  
       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;  
       switch (mode & S_IFMT) {  
       default:  
           init_special_inode(inode, mode, dev);  
           break;  
       case S_IFREG:  
           printk("creat a  file \n");  
           break;  
       case S_IFDIR:  
           inode->i_op = &simple_dir_inode_operations;  
           inode->i_fop = &simple_dir_operations;  
           printk("creat a dir file \n");  

           inode->i_nlink++;  
           break;  
       }  
  }  
  return inode;  
}  
/* SMP-safe  创建iNode的函数 */  
static int aufs_mknod(struct inode *dir, struct dentry *dentry,  
           int mode, dev_t dev)  
{  
  struct inode *inode;  
  int error = -EPERM;  
 /* 判断inode是否存在 如果存在就返回退出函数 */
  if (dentry->d_inode)  
       return -EEXIST;  
 /* 如果inode不存在就调用aufs_get_inode函数创建inode */
  inode = aufs_get_inode(dir->i_sb, mode, dev);  
  if (inode) {  
  /*  */
       d_instantiate(dentry, inode);  
       dget(dentry);  
       error = 0;  
  }  
  return error;  
}  

static int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  
{  
  int res;  
 /* 参数S_IFDIR表示创建一个目录文件的inode */
  res = aufs_mknod(dir, dentry, mode |S_IFDIR, 0);  
  if (!res)  
       dir->i_nlink++;  
  return res;  
}  

static int aufs_create(struct inode *dir, struct dentry *dentry, int mode)  
{  
  return aufs_mknod(dir, dentry, mode | S_IFREG, 0);  
}  

static int aufs_fill_super(struct super_block *sb, void *data, int silent)  
{  
  static struct tree_descr debug_files[] = {{""}};  

  return simple_fill_super(sb, AUFS_MAGIC, debug_files);  
}  

static struct super_block *aufs_get_sb(struct file_system_type *fs_type,  
                int flags, const char *dev_name,  
                void *data)  
{  
  return get_sb_single(fs_type, flags, data, aufs_fill_super);  
}  

static struct file_system_type au_fs_type = {  
  .owner =    THIS_MODULE,  
  .name =     "aufs",  
  .get_sb =   aufs_get_sb,  
  .kill_sb =  kill_litter_super,  
};  

 /* 创建文件的inode和dentry结构 */
static int aufs_create_by_name(const char *name, mode_t mode,  
                 struct dentry *parent,  
                 struct dentry **dentry)  
{  
  int error = 0;  

  /* If the parent is not specified, we create it in the root.  
   * We need the root dentry to do this, which is in the super  
   * block. A pointer to that is in the struct vfsmount that we  
   * have around.  
   */  
   /* 判断是否有父目录 没有就赋予文件系统的根dentry */
  if (!parent ) {  
       if (aufs_mount && aufs_mount->mnt_sb) {  
           parent = aufs_mount->mnt_sb->s_root;  
       }  
  }  
  if (!parent) {  
       printk("Ah! can not find a parent!\n");  
       return -EFAULT;  
  }  

  *dentry = NULL;  
  /* 原子锁  */
  mutex_lock(&parent->d_inode->i_mutex);  

  /* 调用lookup_one_len:首先在父目录下根据名字查找dentry结构 如果存在就返回指针 不存在就创建一个dentry */
  *dentry = lookup_one_len(name, parent, strlen(name));  
  if (!IS_ERR(dentry)) {  
       if ((mode & S_IFMT) == S_IFDIR)  
        /* 这里表示创建一个目录文件的inode */
            error = aufs_mkdir(parent->d_inode, *dentry, mode);  
       else  
       /* 创建一个文件的inode */
            error = aufs_create(parent->d_inode, *dentry, mode);  
  } else  
       error = PTR_ERR(dentry);  
  mutex_unlock(&parent->d_inode->i_mutex);  

  return error;  
}  

/* 创建一个文件 文件是用dentry和inode代表的 这里是创建dentry和inode */
struct dentry *aufs_create_file(const char *name, mode_t mode,  
                  struct dentry *parent, void *data,  
                  struct file_operations *fops)  
{  
  struct dentry *dentry = NULL;  
  int error;  

  printk("aufs: creating file '%s'\n",name);  

  error = aufs_create_by_name(name, mode, parent, &dentry);  
  if (error) {  
       dentry = NULL;  
       goto exit;  
  }  
  if (dentry->d_inode) {  
       if (data)  
            dentry->d_inode->u.generic_ip = data;  
       if (fops)  
            dentry->d_inode->i_fop = fops;  
  }  
exit:  
  return dentry;  
}  

 /* 目录创建 linux中目录也是文件 所以调用aufs_create_file创建文件 传入参数S_IFDIR指明创建的是一个目录 */
struct dentry *aufs_create_dir(const char *name, struct dentry *parent)  
{  
  return aufs_create_file(name,  
                  S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,  
                  parent, NULL, NULL);  
}  

static int __init aufs_init(void)  
{  
  int retval;  
       struct dentry *pslot;  

 /* 将文件系统登记到系统 */
  retval = register_filesystem(&au_fs_type);  

  if (!retval) {  
/* 创建super_block 根dentry 根inode */
       aufs_mount = kern_mount(&au_fs_type);
/* kern_mount错误就卸载文件系统 */
       if (IS_ERR(aufs_mount)) {  
           printk(KERN_ERR "aufs: could not mount!\n");  
           unregister_filesystem(&au_fs_type);  
           return retval;  
       }  
  }  
/* 创建目录和目录下的几个文件 */
  pslot = aufs_create_dir("woman star",NULL);  
  aufs_create_file("lbb", S_IFREG | S_IRUGO, pslot, NULL, NULL);  
  aufs_create_file("fbb", S_IFREG | S_IRUGO, pslot, NULL, NULL);  
  aufs_create_file("ljl", S_IFREG | S_IRUGO, pslot, NULL, NULL);  

  pslot = aufs_create_dir("man star",NULL);  
  aufs_create_file("ldh", S_IFREG | S_IRUGO, pslot, NULL, NULL);  
  aufs_create_file("lcw", S_IFREG | S_IRUGO, pslot, NULL, NULL);  
  aufs_create_file("jw", S_IFREG | S_IRUGO, pslot, NULL, NULL);  

  return retval;  
}  
static void __exit aufs_exit(void)  
{  
/* 退出函数中卸载super_block 根dentry 根inode */
  simple_release_fs(&aufs_mount, &aufs_mount_count);  
  /* 卸载文件系统 */
  unregister_filesystem(&au_fs_type);  
}  
 /* 模块入口出口函数声明 和模块声明 */
module_init(aufs_init);  
module_exit(aufs_exit);  
MODULE_LICENSE("GPL");  
MODULE_DESCRIPTION("This is a simple module");  
MODULE_VERSION("Ver 0.1"); 

a

2、文件系统如何管理目录和文件


3、文件系统的挂载过程


4、文件打开的代码分析



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

文件系统---代码层次深入分析文件系统 的相关文章

  • python实现抢劵_手把手教你用python抢京东大额神券

    一 背景介绍 我们经常能看到京东上有满200减100之类的大额神券 但是当自己激动的等在电脑旁 手拿鼠标 眼盯屏幕 等着倒计时慢慢临近 期待抢到自己喜爱的优惠券 然而最终得到的往往是 券已抢完 为了弥补手速的缺憾 今天我教大家如何用pyth
  • CentOS 8: yum 设置为阿里源

    1 将源文件备份 cd etc yum repos d mkdir backup mv repo backup 2 下载阿里源文件 curl o etc yum repos d CentOS Base repo http mirrors a
  • [Qt学习笔记]Qt动态切换控件样式属性方法

    目录 1 介绍 2 实现过程 3 效果展示 1 介绍 在编程过程中我们一般使用setStyleSheet 函数来设置控件的样式属性 包括颜色 边框 透明度等属性 如果不同的控件和样式直接在代码中设置 会造成无法统一管理的缺点 反复书写样式属
  • C语言怎么用char输出多个字母,c语言输入一个字符串怎么间隔输出

    Q1 c语言中 如何利用指针对字符串每隔几个输出一个 隔三个 输出一个 也就是每四个输出一个 char s abcdefgh char p s int i 0 for p s p p i if i 4 0 putchar p Q2 c语言
  • 等额本息贷款每月还款金额推导过程

    假设贷款总额是A 而每月利息是b 总共360期 目标是计算每个月应该给银多少钱 推导过程如下 设每个月还银行的本金为 m n 1 n
  • Pattern.compile的flag参数

    Pattern compile函数 Pattern Pattern compile String regex int flag regex为正则表达式 flag的取值范围如下 Pattern CANON EQ 当且仅当两个字符的 正规分解
  • (总结许多容易犯的错误)Ubuntu14.04+cuda8.0+gtx1080+cudnn5.1配置教程

    需要注意 不能按照网上大多数cuda8 0 gtx1080的方法来做 因为他们这些方法都忽略了一个重要的问题 NVIDIA官方的版本更新会影响兼容性导致Ubuntu系统无法进入登录界面 例如 cuda 8 0 27 linux版本对应NVI
  • 数组解构赋值与扩展运算符...

    解构 let a b c 1 3 5 扩展运算符
  • 「从0到1搭建自己的UI组件库」-- button组件

    写在前面 我是 沸羊羊 昵称来自于姓名的缩写 fyy 之前呕心沥血经营的博客因手残意外注销 现经营此账号 本人是个小菜 正向着全栈工程师的方向努力着 文章可能并不高产 也很基础 但每写一篇都在用心总结 请大佬勿喷 如果您对编程有兴趣 请关注
  • vue3封装简易的vue-echarts

    项目场景 数据可视化开发 采用的技术栈是vue3 echarts router 问题描述 在vue2中 才开始开发数据可视化大屏 都是用echarts 之后改用为vue echarts组件 但是到了vue3之后 组件会有一些小问题 所以准备
  • 如何强制解锁或删除被占用的文件或文件夹 - ForceDelete绿色强制文件删除工具

    你可能时常遇到无法删除Windows上的文件和文件夹的情况 并且会收到 无法删除文件 访问被拒绝 或 该文件已被其他程序打开 诸如此类的错误消息 这意味着这些文件和文件夹在Windows中被锁定 无法以常规方式删除 你可以试试ForceDe
  • 计算机如何根据人脸估计年龄,人脸图像算法研究(1)

    今天给大家带来一篇 人脸识别中的年龄估计技术 年龄特征作为人类的一种重要生物特征 计算机要如何基于人脸图像估计年龄呢 概述 简单地说 基于人脸图像的年龄估计是指机器根据面部图像推测出人的大概年龄或所属的年龄范围 年龄段 基于人脸图像的年龄估
  • 4.4.5 密码验证(2)

    4 当且仅当含数字和字母的密码验证 如果密码当且仅当包含数字和字母 那么该密码的强度是中等强度 当然 它的安全性一般 以下正则表达式能够验证当且仅当包含数字和字母的密码 da zA Z d a zA Z da zA Z 74 正则表达式 7
  • C++ 的四种类型转换

    背景 C语言中强制类型转换可以随意转换我们想要的类型 格式如下 类型 变量名 那么为什么C 还要引入新的4种类型转换呢 1 新的类型转换控制符可以很好的控制类型转换的过程 允许控制各种类型不同的转换 2 C 的类型转换控制服能告诉程序员或读
  • 【毕业设计】Python_学生校园消费行为

    资源下载 https download csdn net download wouderw 87357462 1 分析学校校园消费行为的目的 分析学生的消费行为和食堂的运营状况 为食堂运营提供建议 构建学生消费细分模型 为学校判定学生的经济
  • VT是什么?怎么打开教程

    装过虚拟机的朋友都知道 要想虚拟出cpu 就必须电脑打开VT VT指的是CPU的虚拟化技术 有了它就可以单CPU模拟多CPU并行 这样才可以虚拟出电脑出来 而如果你的bios没有打开VT的话 是不能创建虚拟机的 下面就教大家怎么打开VT 1
  • 华为员工自曝,工作四年,每天都哭想裸辞!

    架构师大咖 架构师大咖 打造有价值的架构师交流平台 分享架构师干货 教程 课程 资讯 架构师大咖 每日推送 公众号 该公众号已被封禁 进入华为是一项令人向往的机会 但它并不适合每个人 许多人都希望能够进入这家公司 但实际上 它要求员工具备卓
  • 加权回归估计_比率估计与回归估计

    本章讨论简单随机抽样和分层随机抽样下比率估计和回归估 计的构造及性质 要求 掌握总体比率 比率估计量及回归估计量的概念 了解比率估计量 回归估计量的偏倚 方差及方差的估计量 掌握应用比率估计量及回归估计量的条件 抽样调查从本质上看是利用不完
  • 蓝桥杯:拉马车

    目录 题目描述 输入描述 输入为 2 行 2 个串 分别表示 A B 双方初始手里的牌序列 我们约定 输入的串的长度不超过 30 输入输出样例 输入 输出 题目分析 列表 递归 AC代码 Java 题目描述 小的时候 你玩过纸牌游戏吗 有一
  • Linux最基础

    软件包安装的时候 会经常用到 tar zxvf Japan tar gz 如果要做LAMP环境的编译 建立一个LAMP源代码包构建的PHP生产环境 下载的包都是 tar gz 这样的源代码包 创建目录 mkdir 创建文件 touch 命令

随机推荐

  • Apache Commons Compress介绍-Zip压缩解压

    Apache Commons Compress介绍 Zip压缩解压 简述 为什么使用Apache Commons Compress 在使用java自带的ZipFile处理zip文件时报如下错误java lang IllegalArgumen
  • 安装virtualbox时安装程序出现严重错误

    问题 windows 8 1 下virtualbox安装到一半跳出错误窗口被迫终止 窗口如下 virtualbox install fail https img blog csdn net 20160622163138051 解决方法 在服
  • 从头走前端-百度前端技术学院(1)

    记录自己在网上自学加复习的前端笔记 当然还有一些其他涉及的相关知识 问题 在web建站技术中 HTML HTML5 XHTML CSS JavaScript PHP SQL web services是什么 答 首先知道网站的访问过程 1 输
  • navicat 绿化版

    navicat自带注册码 已经绿化 解压到任意目录就可运行 Navicat Premium 是一个可多重连接的数据库管理工具 它可让你以单一程序同时连接到 MySQL Oracle PostgreSQL SQLite 及 SQL Serve
  • 高性能IO模型浅析

    高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型 常见的IO模型有四种 1 同步阻塞IO Blocking IO 即传统的IO模型 2 同步非阻塞IO Non blocking IO 默认创建的socket都是阻塞的 非阻塞IO
  • Python retrying模块

    参见 http segmentfault com a 1190000004085023 github源码 https github com rholder retrying
  • QT信号槽连接方式

    1 QT信号槽主要分两个连接方式 手动和自动 1 1 使用 connect 函数手动连接信号和槽 QObject connect sender SIGNAL signal receiver SLOT slot 自动 1 2 使用 lambd
  • 模板类与函数

    模板类与函数 普通函数 参数和返回值是模板类的实例化版本 函数模板 参数和返回值是某种的模板类 函数模板 参数和返回值是任意类型 支持普通类和模板类和其它类型 模板类可以用于函数的参数和返回值 有三种形式 普通函数 参数和返回值是模板类的实
  • 运用Cookie技术,统计访问次数以及上次访问时间。

    package servlet import java io IOException import java io PrintWriter import java text SimpleDateFormat import java util
  • mysql已经配置且正确_mysql8 参考手册-Connector/J应用程序进行故障排除-1

    16 1 当我尝试使用MySQL Connector J连接到数据库时 出现以下异常 SQLException Server configuration denies access to data source SQLState 08001
  • 【Web自动化测试——代码篇】常用方法——切换

    方法总览 多表单切换 当一个页面存在frame iframe表单嵌套时 WebDriver却只能在一个页面上对元素识别定位 但是对于表单上的嵌套元素无法直接定位 这时候该怎么办呢 Java 1 package JavaTest 2 3 im
  • PAT乙级1042 字符统计 (20 分)

    1042 字符统计 20 分 一 问题描述 请编写程序 找出一段给定文字中出现最频繁的那个英文字母 输入格式 输入在一行中给出一个长度不超过 1000 的字符串 字符串由 ASCII 码表中任意可见字符及空格组成 至少包含 1 个英文字母
  • 23.07.12作业

    思维导图 计算题
  • Provider提供者模式与策略模式的比较

    在这篇文章Provider和Factory的区别 作者提到 可以往工厂里面添加Provider 也就是说Factory里面可能存在着许许多多的Provider 而这些Provider将是最后Factory创建出结果的必要支撑 可以理解为提供
  • 开启硬件加速 导致花屏问题 OpenGlRenderer 0x506 解决办法

    150114 17 08 32 461 I dalvikvm heap 850 Grow heap frag case to 10 342MB for 2457616 byte allocation 150114 17 08 32 542
  • Python实现基于朴素贝叶斯的垃圾邮件分类

    听说朴素贝叶斯在垃圾邮件分类的应用中效果很好 寻思朴素贝叶斯容易实现 就用python写了一个朴素贝叶斯模型下的垃圾邮件分类 在400封邮件 正常邮件与垃圾邮件各一半 的测试集中测试结果为分类准确率95 15 在仅仅统计词频计算概率的情况下
  • 解决Debian系统自动更新软件包的问题

    解决Debian系统自动更新软件包的问题 参考文章 1 解决Debian系统自动更新软件包的问题 2 https www cnblogs com nkqlhqc p 11978565 html 备忘一下
  • android添加依赖出现问题

    出现该问题unspecified on project app resolves to an APK archive which is not supported as a compilation dependency的情形可能是 创建了两
  • hduoj 2010

    水仙花数 Problem Description 春天是鲜花的季节 水仙花就是其中最迷人的代表 数学上有个水仙花数 他是这样定义的 水仙花数 是指一个三位数 它的各位数字的立方和等于其本身 比如 153 1 3 5 3 3 3 现在要求输出
  • 文件系统---代码层次深入分析文件系统

    文件系统对用户来说 最重要的就是创建目录 创建文件 打开文件 和 文件读写 对通常的硬盘文件系统来说 涉及硬盘的读写和硬盘空间管理 从读写文件系统层一直到通用设备层再到硬盘驱动 为了简化 我们给出最简单文件系统 通过这个例子导入文件系统的概