Linux vfs各种operation操作介绍

2023-11-10

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 ()

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

Linux vfs各种operation操作介绍 的相关文章

  • GCC 详细模式输出解释

    我是 Linux 新手 谁能向我解释一下我的 hello world 程序的以下详细模式输出 另外 这些文件是做什么用的crt1 o crti o crtend o crtbegin o and crtn o and lc and lgcc
  • Linux 中的 Windows NAmed Pipes 替代品

    我们正在将现有的 Windows 代码移植到 Linux 我们使用 ACE 作为抽象层 我们使用 Windows 命名管道与多个客户端进行通信并执行重叠操作 linux 下这个相当于什么 我检查了linux命名管道 FIFO 但它们似乎只支
  • 用于 e NetworkManager VPN 连接的 dbus 信号处理程序

    我需要开发一些在建立 VPN 连接时执行的 python 代码 VPN 由 NetworkManager 控制 我试图弄清楚如何为此使用 NM DBUS 事件 使用 dbus monitor system 我能够识别连接信号 signal
  • 每个虚拟主机的错误日志?

    在一台运行 Apache 和 PHP 5 的 Linux 服务器上 我们有多个带有单独日志文件的虚拟主机 我们似乎无法分离 phperror log虚拟主机之间 覆盖此设置
  • PHP mail() 函数不发送邮件

    我有一个小问题 我正在使用一个工作脚本 在我的测试帐户 共享服务器上工作 使用 mail 函数通过 PHP 发送邮件 我刚刚得到了一个专用服务器 但我还无法让该功能发挥作用 在过去的 10 个小时左右的时间里 我阅读了有关 BIND 用于
  • 如何在C程序中直接改变显存映射来绘制像素(无需库函数)

    是否可以通过使用 C 程序更改 RAM 中屏幕 视频即监视器 内存映射中的值来显示黑点 我不想使用任何库函数 因为我的主要目标是学习如何开发简单的操作系统 我尝试访问起始屏幕内存映射 即 0xA0000 在 C 中 我尝试运行该程序 但由于
  • sudo pip install python-Levenshtein 失败,错误代码 1

    我正在尝试在 Linux 上安装 python Levenshtein 库 但每当我尝试通过以下方式安装它时 sudo pip install python Levenshtein 我收到此错误 命令 usr bin python c 导入
  • 设置 Vim 背景颜色

    当我尝试更改背景颜色时 vimrc或者直接在 Vim 中使用以下命令 set background dark 这根本不影响我的背景 也没有light选项 不过 当我运行 gvim 时 看起来还不错 有没有办法在不更改 Konsole 设置的
  • PHP 日志文件颜色

    我正在编写一个 PHP 日志文件类 但我想为写入文件的行添加颜色 我遇到的问题是颜色也会改变终端的颜色 我想要实现的是仅更改写入日志文件的行的颜色 class logClass extends Singleton private funct
  • 使用 terminfo 的终端颜色?

    我正在编写一个 C 类 允许在终端中使用颜色 我希望它适用于每个终端 在支持真彩色 24 位 的终端上打印 在支持它的终端上具有 256 色 6x6x6 其他都是基本的 16 种颜色 我曾经使用 termcap 编写过一次 C 函数 并且我
  • python 可以检测它运行在哪个操作系统下吗?

    python 可以检测操作系统 然后为文件系统构建 if else 语句吗 我需要将 Fn 字符串中的 C CobaltRCX 替换为 FileSys 字符串 import os path csv from time import strf
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • 将 bash 脚本作为守护进程运行

    我有一个脚本 它每 X 次运行我的 PHP 脚本 bin bash while true do usr bin php f my script php echo Waiting sleep 3 done 我怎样才能将它作为守护进程启动 要从
  • 如何清理 Runtime.exec() 中使用的用户输入?

    我需要通过命令行调用自定义脚本 这些脚本需要很少的参数并在 Linux 机器上调用 当前版本容易出现各种shell注入 如何清理用户给出的参数 参数包括登录名和路径 Unix 或 Windows 路径 用户应该能够输入任何可能的路径 该路径
  • 为什么 proc/ID/maps 有多个共享库条目

    我正在查看嵌入式Linux下的proc ID maps 我注意到一些共享库在进程的内存映射中出现了几次 为什么会这样呢 40094000 400d9000 r xp 00000000 b3 09 723 system lib libc so
  • 从sourceforge下载最新版本

    我正在尝试在 bash 脚本中从 Sourceforge 下载最新版本的graphicsmagick wget q https sourceforge net projects graphicsmagick files latest dow
  • 在哪里可以找到所有 C 标准库的源代码?

    我正在寻找所有 C 标准库的完整源代码 也就是说 我正在寻找 stdio h stdlib h string h math h 等的源代码 我想看看它们是如何创建的 我认为这取决于不同的平台 但 Linux 或 Windows 都会受到欢迎
  • 如何从python导入路径中删除当前目录

    我想使用 Mercurial 存储库hg本身 也就是说 我克隆了 Mercurialhttps www mercurial scm org repo hg https www mercurial scm org repo hg并想运行一些h
  • Docker 容器可以访问 DNS,但无法解析主机

    我在运行 docker 容器时遇到一个有趣的问题 突然间 我无法从容器内解析 DNS 这是一个概要 一切都没有解决 apt get pip 一次性 ping 容器等正在运行docker run it dns 8 8 8 8 ubuntu p
  • 无法使用 tar -cvpzf 解压完整目录

    把我的头敲在这上面 I used tar cvpzf file tar gz压缩一个完整的目录 我将文件移动到另一台服务器 并尝试解压缩复制存档的目录 无法使其发挥作用 bash 3 2 tar xvpzf news tar gz tar

随机推荐