Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Linux系统调用如何与文件系统交互_C_Linux_Filesystems_System Calls - Fatal编程技术网

C Linux系统调用如何与文件系统交互

C Linux系统调用如何与文件系统交互,c,linux,filesystems,system-calls,C,Linux,Filesystems,System Calls,最近我遇到了这样的练习: 给定Linux C语言程序中的系统调用序列: 考虑到4 KB的块大小和4字节的索引块指针,绘制通过这些操作修改的文件系统数据结构和磁盘块 对于第一次系统调用(open),我了解了它是如何工作的,并以这种方式对其进行了模式化: 现在,跳过绘图部分(我意识到这将很难回答),我想了解lseek和write在索引节点和索引块(无论它们是什么)方面是如何工作的 我试图计算出lseek计算正确的inode(块大小已知),但仍然不知道它实际上是如何工作的。在Linux中,这些系统调

最近我遇到了这样的练习:

给定Linux C语言程序中的系统调用序列:

考虑到4 KB的块大小和4字节的索引块指针,绘制通过这些操作修改的文件系统数据结构和磁盘块

对于第一次系统调用(
open
),我了解了它是如何工作的,并以这种方式对其进行了模式化:

现在,跳过绘图部分(我意识到这将很难回答),我想了解
lseek
write
在索引节点和索引块(无论它们是什么)方面是如何工作的


我试图计算出
lseek
计算正确的inode(块大小已知),但仍然不知道它实际上是如何工作的。

在Linux中,这些系统调用与虚拟文件系统(VFS)交互。VFS在实际文件系统上构建了一个抽象,它定义了一些有用的数据结构来组织文件系统

  • 索引节点表示磁盘上的真实文件。通过inode结构不仅可以访问inode块,还可以访问磁盘上的数据块
  • 目录条目表示路径的一部分。d_条目并不总是指磁盘上的真实文件。如果它引用磁盘上的目录,则会有一个指向目录文件的inode结构的指针
  • 文件表示进程打开的文件。结构中还有一个指向其d_项的指针
以下是
文件
结构的片段:

struct file {
    // ... other attributes
    struct path     f_path;
    #define f_dentry    f_path.dentry
    #define f_vfsmnt    f_path.mnt
    const struct file_operations    *f_op;
};
struct file_operations {
    // ... other operations
    struct module *owner;
    loff_t (*llseek) (struct file *, loff_t, int);
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
}
这些对象都有一个操作列表字段。VFS定义这些操作,底层文件系统实现这些操作或使用VFS提供的常规实现


Syscall
open()
创建file对象,其他系统调用如
lseek()
只需获取
file
对象(通过Fd)并调用操作列表中相应的函数,如
write()
将调用
f->f_op->write(f…)
,然后文件系统可以按照
文件->数据项->索引节点
路径访问磁盘上的文件

open()
确定inode-其他函数使用该信息。您需要一个打开的文件描述符表和一个打开的文件描述表(这可能就是您所说的“文件表”,但我不确定)。描述(与描述符相反)保存寻道偏移量(文件中的当前位置)。一般来说,多个描述符可以引用一个描述-这些描述符不必都在同一个过程中,尽管在您的示例代码中,只涉及一个过程。这是有意义的。因此,lseek只需更改描述表中的当前偏移量,然后搜索正确的块(如果有)?
lseek()
不搜索正确的块;不需要。这是下一个需要跟踪块的I/O操作,与移动操作相反。例如,您可以查找文件当前结尾以外的路径。接下来会发生什么取决于您是读(EOF)还是写(写入新材料,任何跳过的块都被视为所有字节零;包含当前EOF的最后一个块的尾部和当前块的开头可能需要强制归零)。不能从开始处使用负偏移量,否则,
lseek()
会成功(取决于类型限制)。
struct file {
    // ... other attributes
    struct path     f_path;
    #define f_dentry    f_path.dentry
    #define f_vfsmnt    f_path.mnt
    const struct file_operations    *f_op;
};
struct file_operations {
    // ... other operations
    struct module *owner;
    loff_t (*llseek) (struct file *, loff_t, int);
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
}