如何正确使用 strace -e read=fd 选项?

如何正确使用 strace -e read=fd 选项?

我正在尝试监视正在运行的进程中特定文件描述符的读取活动。这是我正在测试各种解决方案的 C++ 测试平台:

#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <iostream>

int main()
{
    const int fd1=open("/tmp/testfile", O_RDWR|O_CREAT);
    const int fd2=open("/tmp/testfile", O_RDONLY);
    write(fd1, "Hello, world!", 13);
    std::cout << "PID: " << getpid() << ", fds: " << fd1 << "," << fd2 << "\n";
    for(;;)
    {
        char b;
        if(!read(fd1,&b, 1))
            lseek(fd1,0,SEEK_SET);
    }
}

其典型输出为:

PID: 14992, fds: 3,4

因此,我尝试使用 strace 来跟踪文件描述符 3 的读取:

strace -p 14992 -e trace=none -e read=3

我收到的只是消息strace: Process 14992 attached,仅此而已。如果我跟踪所有read系统调用,我确实会得到很多输出:

$ strace -p 14992 -e trace=read
strace: Process 14992 attached
read(3, "", 1)                          = 0
read(3, "H", 1)                         = 1
read(3, "e", 1)                         = 1
read(3, "l", 1)                         = 1
read(3, "l", 1)                         = 1
read(3, "o", 1)                         = 1
read(3, ",", 1)                         = 1
read(3, " ", 1)                         = 1
<...>

但 strace 手册说-e read=set

请注意,这独立于read由选项 -e trace=read 控制的系统调用的正常跟踪。

所以我认为 mytrace=none应该避免跟踪与我的read=3选项无关的任何内容是正确的。

显然,我做错了什么。那么,我实际上应该如何使用 strace 来仅跟踪read系统调用,并且仅在何时跟踪fd==3?请注意,使用过滤输出grep不是一个选项,因为它会减慢我要跟踪的实际应用程序的速度。

答案1

我不确定如何解释您从联机帮助页中引用的句子,但禁用所有跟踪也会禁用所有read跟踪:I/O 跟踪在跟踪系统调用后发生,并且仅发生在启用的系统调用上。

strace -e trace=none -e read=3

意思是“禁用所有系统调用跟踪,并且每当跟踪从文件描述符 3 读取的系统调用时,转储其 I/O”。

strace -e read -e read=3

显示对文件描述符 3 的调用read以及从文件描述符 3 读取的所有信息,但它read根本不过滤一般系统调用跟踪,仅过滤 I/O 转储。

换句话说,read=3不过滤所有跟踪选项;它请求从文件描述符 3 读取的 I/O 转储。

查看strace源代码,似乎没有办法完成您想要的操作。

相关内容