代码之家  ›  专栏  ›  技术社区  ›  sly493

是否有一个linux命令(沿着cat或dd行)允许我指定read系统调用的偏移量?

  •  0
  • sly493  · 技术社区  · 10 年前

    我正在为一个操作系统类做作业,我们正在使用 FUSE .

    我们实现的唯一一个操作是read()系统调用,我无法测试到我满意的程度。我很难找到一种方法来调用read()系统调用,偏移量不是0。

    我尝试了答案中提到的一些命令(如dd、head和tail) this question ,但当它们到达我的read()系统调用实现时,偏移量为0。为了澄清,当我调用这些命令时,我(在调用终端)收到了文件中在调用中指定的字节,但在另一个显示由FUSE处理的系统调用的终端,以及我的实现中,它显示我的read()系统调用的实现总是以偏移量0(通常大小为4096,我认为这是我使用的真实linux文件系统的块大小)调用。我假设这些命令在4096字节的块中进行read()系统调用,然后在内部(即,在dd、head或tail命令的代码中,而不是通过系统调用)将输出修改为调用终端上看到的内容。

    是否有任何命令(或脚本)可以运行(或在脚本的情况下编写然后运行),允许我使用不同的偏移值测试此系统调用?

    1 回复  |  直到 7 年前
        1
  •  0
  •   sly493    10 年前

    我弄明白了我遇到的问题。为了子孙后代,我会记录下答案,而不仅仅是删除我的问题,因为答案不一定容易找到。

    本质上,问题发生在FUSE中。FUSE默认不使用直接I/O(这绝对是正确的默认设置,请不要误会),这导致读取大小为4096的块 (these are the result of FUSE using a page cache of file contents [AKA a file content cache] in the kernel) 。对于我想要测试的内容(如问题中所解释的),我需要启用直接I/O。有一个 few ways of doing this 但我最简单的方法就是通过 -o direct_io 作为命令行参数。这对我有用,因为我使用 fuse_main 调用 main 我的程序的功能。

    所以我的 主要的 函数如下所示:

    int main(int argc, char *argv[])
    {
        return fuse_main(argc, argv, &my_operations_structure, NULL);
    }
    

    我可以这样调用我的程序(我使用 -d 选项 -o直接_io 选项,以便显示FUSE正在处理的系统调用和程序的输出/调试信息):

    ./prog_name -d -o direct_io test_directory
    

    然后,我用以下简单的测试程序测试了我的程序(我知道我不做很多错误检查,但这个程序只用于一些快速和肮脏的测试):

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    int main(int argc, char *argv[])
    {
        FILE * file;
        char buf[4096];
    
        int fd;
    
        memset(&buf[0], 0, sizeof(buf));
    
        if (argc != 4)
        {
            printf("usage: ./readTest [size] [offset] [filename]\n");
            return 0;
        }
    
        file = fopen(argv[3], "r");
        if (file == NULL)
        {
            printf("Couldn't open file\n");
            return -1;
        }   
    
        fd = fileno(file);
    
        pread(fd, (void *) buf, atoi(argv[1]), (off_t) atoi(argv[2]));
    
        printf("%s\n", buf);
    
        return 0;
     }