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_Resources - Fatal编程技术网

C++ 如何在Linux中检测文件访问?

C++ 如何在Linux中检测文件访问?,c++,linux,resources,C++,Linux,Resources,我有一堆流和数据处理应用程序,我偶尔需要监视它们,这意味着我需要知道它们读取什么文件。这主要是为了帮助打包测试用例,但在调试时也很有用 有没有一种方法可以以生成这样一个列表的方式运行可执行文件 我有两个想法: 我可以调用一个命令,该命令调用我的应用程序。类似GDB的东西。我调用GDB,给它一个指向可执行文件的路径和一些参数,然后GDB为我调用它。也许有类似于告诉我如何使用系统资源的事情 也许是更有趣(但不必要的旁道)的解决方案。 创建一个名为libc.so的库,它实现了fopen(以及其他一些)

我有一堆流和数据处理应用程序,我偶尔需要监视它们,这意味着我需要知道它们读取什么文件。这主要是为了帮助打包测试用例,但在调试时也很有用

有没有一种方法可以以生成这样一个列表的方式运行可执行文件

我有两个想法:

  • 我可以调用一个命令,该命令调用我的应用程序。类似GDB的东西。我调用GDB,给它一个指向可执行文件的路径和一些参数,然后GDB为我调用它。也许有类似于告诉我如何使用系统资源的事情
  • 也许是更有趣(但不必要的旁道)的解决方案。
  • 创建一个名为libc.so的库,它实现了fopen(以及其他一些)
  • 将LD_LIBRARY_路径更改为指向新库
  • 复制真实libc.so并在编辑器中重命名fopen(可能是nepof)
  • “我的库”加载副本并根据需要调用重命名的函数以提供fopen功能
  • 调用应用程序,然后调用我的代理fopen
  • 备选方案#1当然是更可取的方案,但也欢迎对如何更容易做到#2发表评论

    man strace 
    
    示例(假设2343是进程id):


    一种选择是使用strace:

    strace -o logfile -eopen yourapp
    
    这将记录所有文件打开事件,但可能会造成严重的性能损失。然而,它的优点是易于使用

    另一种选择是使用LD_预加载。这与您的选项2相对应。基本思想是这样做:

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <dlfcn.h>
    
    int open(const char *fn, int flags) {
        static int (*real_open)(const char *fn, int flags);
    
        if (!real_open) {
            real_open = dlsym(RTLD_NEXT, "open");
        }
    
        fprintf(stderr, "opened file '%s'\n", fn);
        return real_open(fn, flags);
    }
    
    并使用eg运行您的程序:

    $ LD_PRELOAD=$PWD/preload-example.so cat /dev/null
    opened file '/dev/null'
    
    这样的开销要小得多

    但是,请注意,打开文件还有其他入口点-例如,fopen()、openat(),或许多旧式兼容性入口点之一:

    00000000000747d0 g    DF .text      000000000000071c  GLIBC_2.2.5 _IO_file_fopen
    0000000000068850 g    DF .text      000000000000000a  GLIBC_2.2.5 fopen
    000000000006fe60 g    DF .text      00000000000000e2  GLIBC_2.4   open_wmemstream
    00000000001209c0  w   DF .text      00000000000000ec  GLIBC_2.2.5 posix_openpt
    0000000000069e50 g    DF .text      00000000000003fb  GLIBC_2.2.5 _IO_proc_open
    00000000000dcf70 g    DF .text      0000000000000021  GLIBC_2.7   __open64_2
    0000000000068a10 g    DF .text      00000000000000f5  GLIBC_2.2.5 fopencookie
    000000000006a250 g    DF .text      000000000000009b  GLIBC_2.2.5 popen
    00000000000d7b10  w   DF .text      0000000000000080  GLIBC_2.2.5 __open64
    0000000000068850 g    DF .text      000000000000000a  GLIBC_2.2.5 _IO_fopen
    00000000000d7e70  w   DF .text      0000000000000020  GLIBC_2.7   __openat64_2
    00000000000e1ef0 g    DF .text      000000000000005b  GLIBC_2.2.5 openlog
    00000000000d7b10  w   DF .text      0000000000000080  GLIBC_2.2.5 open64
    0000000000370c10 g    DO .bss       0000000000000008  GLIBC_PRIVATE _dl_open_hook
    0000000000031680 g    DF .text      0000000000000240  GLIBC_2.2.5 catopen
    000000000006a250 g    DF .text      000000000000009b  GLIBC_2.2.5 _IO_popen
    0000000000071af0 g    DF .text      000000000000026a  GLIBC_2.2.5 freopen64
    00000000000723a0 g    DF .text      0000000000000183  GLIBC_2.2.5 fmemopen
    00000000000a44f0  w   DF .text      0000000000000088  GLIBC_2.4   fdopendir
    00000000000d7e70 g    DF .text      0000000000000020  GLIBC_2.7   __openat_2
    00000000000a3d00  w   DF .text      0000000000000095  GLIBC_2.2.5 opendir
    00000000000dcf40 g    DF .text      0000000000000021  GLIBC_2.7   __open_2
    00000000000d7b10  w   DF .text      0000000000000080  GLIBC_2.2.5 __open
    0000000000074370 g    DF .text      00000000000000d7  GLIBC_2.2.5 _IO_file_open
    0000000000070b40 g    DF .text      00000000000000d2  GLIBC_2.2.5 open_memstream
    0000000000070450 g    DF .text      0000000000000272  GLIBC_2.2.5 freopen
    00000000000318c0 g    DF .text      00000000000008c4  GLIBC_PRIVATE __open_catalog
    00000000000d7b10  w   DF .text      0000000000000080  GLIBC_2.2.5 open
    0000000000067e80 g    DF .text      0000000000000332  GLIBC_2.2.5 fdopen
    000000000001e9b0 g    DF .text      00000000000003f5  GLIBC_2.2.5 iconv_open
    00000000000daca0 g    DF .text      000000000000067b  GLIBC_2.2.5 fts_open
    00000000000d7d60  w   DF .text      0000000000000109  GLIBC_2.4   openat
    0000000000068850  w   DF .text      000000000000000a  GLIBC_2.2.5 fopen64
    00000000000d7d60  w   DF .text      0000000000000109  GLIBC_2.4   openat64
    00000000000d6490 g    DF .text      00000000000000b6  GLIBC_2.2.5 posix_spawn_file_actions_addopen
    0000000000121b80 g    DF .text      000000000000008a  GLIBC_PRIVATE __libc_dlopen_mode
    0000000000067e80 g    DF .text      0000000000000332  GLIBC_2.2.5 _IO_fdopen
    
    为了完整性,您可能需要钩住所有这些,至少,没有前缀u的应该钩住。尤其要确保单独钩住fopen,因为LD_预加载库不会钩住从fopen()到open()的libc内部调用


    strace也有一个类似的警告——还有“openat”系统调用,根据您的体系结构,可能还有其他遗留系统调用。但是没有LD_PRELOAD hook那么多,所以如果您不介意性能的影响,它可能是一个更简单的选择。

    我使用的是:

    strace -o file.txt ./command
    
    那么你可以

    cat file.txt | grep open
    
    获取程序打开的所有文件的列表。

    另请参见
    strace -o file.txt ./command
    
    cat file.txt | grep open