Linux vfs各种operation操作介绍

news2024/11/17 11:50:01
1.ext4文件系统定义的各种操作
//普通文件操作
const struct file_operations ext4_file_operations = {
    .llseek     = ext4_llseek,
    .read_iter  = generic_file_read_iter,
    .write_iter = ext4_file_write_iter,
    .unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl   = ext4_compat_ioctl,
#endif
    .mmap       = ext4_file_mmap,
    .open       = ext4_file_open,
    .release    = ext4_release_file,
    .fsync      = ext4_sync_file,
    .splice_read    = generic_file_splice_read,
    .splice_write   = iter_file_splice_write,
    .fallocate  = ext4_fallocate,
};

//目录文件操作
const struct file_operations ext4_dir_operations = {
    .llseek     = ext4_dir_llseek,
    .read       = generic_read_dir,
    .iterate    = ext4_readdir,
    .unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl   = ext4_compat_ioctl,
#endif
    .fsync      = ext4_sync_file,
    .open       = ext4_dir_open,
    .release    = ext4_release_dir,
};    

//普通文件inode操作
const struct inode_operations ext4_file_inode_operations = {                                                                                                                                                        
    .setattr    = ext4_setattr,
    .getattr    = ext4_getattr,
    .setxattr   = generic_setxattr,
    .getxattr   = generic_getxattr,
    .listxattr  = ext4_listxattr,
    .removexattr    = generic_removexattr,
    .get_acl    = ext4_get_acl,
    .set_acl    = ext4_set_acl,
    .fiemap     = ext4_fiemap,
};


/*
 * 目录文件的inode操作
 */
const struct inode_operations ext4_dir_inode_operations = {                                                                                                                                                         
    .create     = ext4_create,
    .lookup     = ext4_lookup,
    .link       = ext4_link,
    .unlink     = ext4_unlink,
    .symlink    = ext4_symlink,
    .mkdir      = ext4_mkdir,
    .rmdir      = ext4_rmdir,
    .mknod      = ext4_mknod,
    .tmpfile    = ext4_tmpfile,
    .rename2    = ext4_rename2,
    .setattr    = ext4_setattr,
    .setxattr   = generic_setxattr,
    .getxattr   = generic_getxattr,
    .listxattr  = ext4_listxattr,
    .removexattr    = generic_removexattr,
    .get_acl    = ext4_get_acl,
    .set_acl    = ext4_set_acl,
    .fiemap         = ext4_fiemap,
};

由于目录也是一种文件,而目录操作和普通文件操作不同,所以文件系统需要定义两种file_operations,创建普通文件和目录文件时候都要创建inode对象,inode对象中包含两个重要的成员:i_op和i_fop,分别代表inode_operations和file_operations,要根据不同文件类型,给其inode赋予不同的结构体:

 

2.vfs调用路径举例
2.1 ls命令

通过strace观察ls命令分两步:1)打开目录 2)读取遍历目录

openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
getdents(3, /* 320 entries */, 32768)   = 10648

2.1.1 打开目录:

openat对应的操作调用栈可以看到调用路径:vsys_openat ->vfs_open->ext4_dir_open

vfs_open由于是操作的目录文件,触发的是目录的open,代码如下:

static int do_dentry_open(struct file *f,
              struct inode *inode,
              int (*open)(struct inode *, struct file *),
              const struct cred *cred)
    {
    ...
    if (!open)
        //这里f对应的时候一个目录,所以其f_open对应的是ext4_dir_operations这个file_operations
        open = f->f_op->open;
    if (open) {
        error = open(inode, f);
        if (error)
            goto cleanup_all;
    ...
    }

 内核调用栈:

#0  ext4_dir_open (inode=0xffff88000647c508, filp=0xffff880006baec00) at fs/ext4/dir.c:614
#1  0xffffffff811725ef in do_dentry_open (f=0xffff880006baec00,	inode=0xffff88000647c508, open=0xffffffff811e7b58 <ext4_dir_open>, cred=0x1 <irq_stack_union+1>) at fs/open.c:753
#2  0xffffffff8117345c in vfs_open (path=0xffffc9000184fde8, file=0xffff880006baec00, cred=0xffff8800070d1540) at fs/open.c:866
#3  0xffffffff81183ccc in do_last (opened=<optimized out>, op=<optimized out>, file=<optimized out>, nd=<optimized out>) at fs/namei.c:3331
#4  path_openat (nd=0xffffc9000184fde8,	op=0xffffc9000184fefc, flags=0)	at fs/namei.c:3454
#5  0xffffffff81183f39 in do_filp_open (dfd=105366792, pathname=0xffff880006baec00, op=0xffffc9000184fefc) at fs/namei.c:3489
#6  0xffffffff811737fb in do_sys_open (dfd=-100, filename=0xffff880006baec00 "", flags=624640, mode=1) at fs/open.c:1053
#7  0xffffffff811738c1 in SYSC_openat (mode=<optimized out>, flags=<optimized out>, filename=<optimized out>, dfd=<optimized out>) at fs/open.c:1080
#8  SyS_openat (dfd=-131941289966328, filename=-131941282419712, flags=0, mode=1) at fs/open.c:1074
#9  0xffffffff818c1460 in entry_SYSCALL_64_fastpath () at arch/x86/entry/entry_64.S:204
#10 0x0000000000000006 in irq_stack_union ()
#11 0x0000000000000000 in ?? ()

 2.1.2 读取目录:

#0  ext4_readdir (file=0xffff880006bae500, ctx=0xffff88000647c508) at fs/ext4/dir.c:108
#1  0xffffffff81186626 in iterate_dir (file=0xffff880006bae500,	ctx=0xffffc9000184fef8)	at fs/readdir.c:50
#2  0xffffffff81186ac7 in SYSC_getdents (count=<optimized out>,	dirent=<optimized out>,	fd=<optimized out>) at fs/readdir.c:230
#3  SyS_getdents (fd=-131941282421504, dirent=-60473114034440, count=32768) at fs/readdir.c:211
#4  0xffffffff818c1460 in entry_SYSCALL_64_fastpath () at arch/x86/entry/entry_64.S:204
#5  0x000000000088ac38 in ?? ()
#6  0x0000000000008041 in exception_stacks ()
Backtrace stopped: not enough registers	or memory available to unwind further

某个目录下执行ls命令,触发的时候目录文件的遍历操作,调用的是file_operations ext4_dir_operations的iterate操作,最终调用到ext4_readdir函数。

2.2 mkdir命令

vfs调用入口:

int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
    int error = may_create(dir, dentry);
    unsigned max_links = dir->i_sb->s_max_links;

    if (error)
        return error;

    if (!dir->i_op->mkdir)
        return -EPERM;

    mode &= (S_IRWXUGO|S_ISVTX);
    error = security_inode_mkdir(dir, dentry, mode);
    if (error)
        return error;

    if (max_links && dir->i_nlink >= max_links)
        return -EMLINK;

    error = dir->i_op->mkdir(dir, dentry, mode);
    if (!error)
        fsnotify_mkdir(dir, dentry);
    return error;
}

内核调用栈:

(gdb) bt
#0  ext4_mkdir (dir=0xffff880006485588,	dentry=0xffff880005a5d900, mode=511) at fs/ext4/namei.c:2638
#1  0xffffffff811805f6 in vfs_mkdir (dir=0xffff880006485588, dentry=0xffff880005a5d900,	mode=511) at fs/namei.c:3735
#2  0xffffffff811842ae in SYSC_mkdirat (mode=511, pathname=<optimized out>, dfd=<optimized out>) at fs/namei.c:3758
#3  SyS_mkdirat (dfd=-131941289929336, pathname=-131941300578048, mode=511) at fs/namei.c:3742
#4  0xffffffff811842f7 in SYSC_mkdir (mode=<optimized out>, pathname=<optimized out>) at fs/namei.c:3769
#5  SyS_mkdir (pathname=-131941289929336, mode=-131941300578048) at fs/namei.c:3767
#6  0xffffffff818c1460 in entry_SYSCALL_64_fastpath () at arch/x86/entry/entry_64.S:204
#7  0x00007ffc4362cfe8 in ?? ()
#8  0x0000000000000000 in ?? ()
2.3 cd命令

内核调用栈:

#0  ext4_lookup (dir=0xffff88000647c508, dentry=0xffff88000647c508, flags=3) at fs/ext4/namei.c:1573
#1  0xffffffff8117fc70 in lookup_slow (name=0xffff88000647c508,	dir=0xffff880005974000,	flags=3) at fs/namei.c:1653
#2  0xffffffff811815e1 in walk_component (nd=0xffffc900000b3de8, flags=0) at fs/namei.c:1774
#3  0xffffffff81181ce1 in lookup_last (nd=<optimized out>) at fs/namei.c:2245
#4  path_lookupat (nd=0xffffc900000b3de8, flags=93798400, path=0xffffc900000b3f20) at fs/namei.c:2257
#5  0xffffffff81182428 in filename_lookup (dfd=105366792, name=0xffff880006b75000, flags=3, path=0xffffc900000b3f20, root=0x656d6f68) at fs/namei.c:2291
#6  0xffffffff81182551 in user_path_at_empty (dfd=-100,	name=0xffff88000647c508 "\355A\v", flags=3, path=0xffffc900000b3f20, empty=0x656d6f68) at fs/namei.c:2545
#7  0xffffffff81172fa1 in user_path_at (path=<optimized out>, flags=<optimized out>, name=<optimized out>, dfd=<optimized out>)	at ./include/linux/namei.h:55
#8  SYSC_chdir (filename=<optimized out>) at fs/open.c:441
#9  SyS_chdir (filename=-131941289966328) at fs/open.c:435
#10 0xffffffff818c1460 in entry_SYSCALL_64_fastpath () at arch/x86/entry/entry_64.S:204
#11 0x0000000000000009 in irq_stack_union ()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/700404.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python基础】- break和continue语句(文末送书4本)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

6 图像处理实现螺纹识别案例(matlab程序)

学习目的&#xff1a;学习识别案例掌握识别方法 2.代码 clear;clc;close all Iimread(luowen1.bmp); %读取螺纹图片 try Irgb2gray(I); %如果是RGB图&#xff0c;则转换成灰度图 catch end figure imshow(I) title(原图&#xff08;半边螺纹&#xff09;) f…

基于pyqt和卷积网络CNN的中文汉字识别

直接上效果演示图&#xff1a; 通过点击按钮可以实现在画板上写汉字识别和加载图片识别两个功能。 视频演示和demo仓库地址在b站视频001期&#xff1a; 到此一游7758258的个人空间-到此一游7758258个人主页-哔哩哔哩视频 所有代码展示&#xff1a; 十分的简洁&#xff0c;主…

【从零开始学习JAVA | 第二十六篇】泛型补充知识

目录 前言&#xff1a; 泛型的更多应用&#xff1a; 泛型类&#xff1a; 泛型方法&#xff1a; 泛型方法&#xff1a; 总结&#xff1a; 前言&#xff1a; 在上一篇文章中我们介绍了泛型的基础知识&#xff0c;也就是在创建集合的时候用到泛型&#xff0c;此时的泛型更多…

关于内存颗粒的地址映射

即便从软件角度&#xff0c;抛开地址译码器讨论内存颗粒中指定位置处的地址&#xff08;DDR中的指定位置的电容&#xff09;也是没有意义的。晶体管没有绝对地址&#xff0c;就如同地理测量中测定位置前需要确定坐标系一样&#xff0c;同一个位置在不同的坐标系中的地址描述可以…

【CVRP测评篇】 算法性能如何?来测!

我跨越了2100015秒的距离&#xff0c;为你送上更全面的算法性能评测。 目录 往期优质资源1 CVRP数据集2 实验准备2.1 计算机配置2.2 调参方法2.3 参数设定2.4 实验方法 3 实验结果3.1 最优解统计3.1.1各数据集上的算法性能对比3.1.2 求解结果汇总3.1.3小结一下3.1.4 还有话说 3…

使用 RedisTemplate 对象的 opsForValue() 方法获取 Redis 中的值获取不到

问题 使用 RedisTemplate 对象的 opsForValue() 方法获取 Redis 中的值获取不到 详细问题 笔者代码如下 1 使用 ValueOperations 对象的 set() 方法将一个键值对存储到 Redis 中 valueOperations.set("order:" user.getId() ":" goods.getId(), sec…

【Redis】2、Redis应用之【根据 Session 和 Redis 进行登录校验和发送短信验证码】

目录 一、基于 Session 实现登录(1) 发送短信验证码① 手机号格式后端校验② 生成短信验证码 (2) 短信验证码登录、注册(3) 登录验证① 通过 SpringMVC 定义拦截器② ThreadLocal (4) 集群 Session 不共享问题 二、基于 Redis 实现共享 session 登录(1) 登录之后&#xff0c;缓…

23款迈巴赫S480升级原厂10°后轮转向系统,减少转弯半径

就是低速的情况下&#xff0c;有更强的机动性&#xff0c;前后车轮的不同转动方向使得车辆可以凭借更更小转弯半径实现转向&#xff0c;在特定的狭窄路段或者停车时&#xff0c;车辆的操控性大大提升&#xff0c;而内轮差也缩小也增大了转向的安全性。 高速的情况下&#xff0…

C. Road Optimization(dp)

Problem - 1625C - Codeforces 火星政府不仅对优化太空飞行感兴趣&#xff0c;还希望改进该行星的道路系统。 火星上最重要的高速公路之一连接着奥林匹克城和西多尼亚的首都Kstolop。在这个问题中&#xff0c;我们只考虑从Kstolop到奥林匹克城的路线&#xff0c;而不考虑相反的…

技术创举!比亚迪-汉上的实景三维导航...

实景三维技术的发展日新月异&#xff0c;但在应用中却一直深陷内存占用、渲染缓慢、加载卡顿和模型塌陷等问题。对此&#xff0c;大势智慧率先推出海量数据轻量化技术&#xff0c;在业内首次实现实景三维模型在车机系统的直接浏览&#xff0c;展示了轻量化技术赋能实景三维应用…

面试Dubbo ,却问我和Springcloud有什么区别?

Dubbo 、Springcloud? 这两有关系&#xff1f; 前言一、RPC 框架的概念1. 什么是RPC框架2. RPC 和 普通通信 的区别 二、常用 RPC 框架1. Dubbo2. gRPC3. Thrift4. Feign 三、dubbo 与 Springcloud1. Dubbo 的模型2. Springcloud3. dubbo 与 Springcloud 的区别 前言 提到Dub…

若隐若现的芯片

先看效果&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>若隐若现的芯片</title><script src"https://unpkg.co/gsap3/dist/gsap.min.js">…

HBase(5):导入测试数据集

1 需求 将ORDER_INFO.txt 中的HBase数据集&#xff0c;我们需要将这些指令放到HBase中执行&#xff0c;将数据导入到HBase中。 可以看到这些都是一堆的put语句。那么如何才能将这些语句全部执行呢&#xff1f; 2 执行command文件 2.1 上传command文件 将该数据集文件上传到指…

单点登录原理

单点登录原理 一、什么是单点登录 单点登录英文全称Single Sign On&#xff0c;简称SSO。指在多系统应用群中登录一个系统&#xff0c;便可在其他所有系统中得到授权而无需再次登录&#xff0c;包括单点登录与单点注销两部分。 二、为什么需要单点登录 在一些子系统用户信息…

初识Go语言25-数据结构与算法【堆、Trie树、用go中的list与map实现LRU算法、用go语言中的map和堆实现超时缓存】

文章目录 堆Trie树练习-用go中的list与map实现LRU算法练习-用go语言中的map和堆实现超时缓存 堆 堆是一棵二叉树。大根堆即任意节点的值都大于等于其子节点。反之为小根堆。   用数组来表示堆&#xff0c;下标为 i 的结点的父结点下标为(i-1)/2&#xff0c;其左右子结点分别为…

Python图像锐化及边缘检测(Roberts、Prewitt、Sobel、Lapllacian、Canny、LOG)

目录 图像锐化概述 算法方法介绍 代码实现 效果展示 图像锐化概述 图像锐化(image sharpening)是补偿图像的轮廓&#xff0c;增强图像的边缘及灰度跳变的部分&#xff0c;使图像变得清晰&#xff0c;分为空间域处理和频域处理两类。图像锐化是为了突出图像上地物的边缘、轮…

Docker|kubernetes|本地镜像批量推送到Harbor私有仓库的脚本

前言&#xff1a; 可能有测试环境&#xff0c;而测试环境下有N多的镜像&#xff0c;需要批量导入到自己搭建的Harbor私有仓库内&#xff0c;一般涉及到批量的操作&#xff0c;自然还是使用脚本比较方便。 本文将介绍如何把某个服务器的本地镜像 推送到带有安全证书的私有Harb…

【P61】JMeter JDBC Connection Configuration

文章目录 一、JDBC Connection Configuration 参数说明二、准备工作 一、JDBC Connection Configuration 参数说明 可以给数据源配置不同的连接池&#xff0c;供后续 JDBC 采样器使用&#xff1b;使用前请将对应的数据库驱动复制到 $JMETER_HOME/lib/ 或者 $JMETER_HOME/lible…

使用注解开发

使用注解开发 为了方便查看测试结果以及方便调试&#xff0c;先熟悉和配置日志。 日志 日志工厂 如果一个数据库操作出现了异常、需要进行排错&#xff0c;可以通过查看日志的方式实现。 Mybatis内置的日志工厂能够提供日志功能&#xff0c;具体的日志实现有以下几种&#xff…