通过套接字文件描述符上的ioctl调用获取数据包时间戳

Gio*_*Gio 7 c sockets embedded-linux

我正在研究运行嵌入式Linux的系统.我正在尝试从我在套接字上收到的流中获取数据包时间戳.

创建套接字后,我执行以下操作:

if (fd != -1) {
    int enabled = 1;
    setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &enabled, sizeof(enabled);
}
Run Code Online (Sandbox Code Playgroud)

之后我绑定套接字,套接字的类型为SOCK_STREAM.我通过调用函数成功地在套接字上接收数据recv(fd, buf, size, 0).现在,为了获得接收数据的时间戳,我目前正在尝试以下方法:

ret = recv(fd, buf, size, 0);
if (ret > 0) {
    struct timeval tv_ioctl;
    tv_ioctl.tv_sec = 0;
    tv_ioctl.tv_usec = 0;
    int error = ioctl(fd, SO_TIMESTAMP, &tv_ioctl);
    printf("%ld.%ld - error = %d", (long int)tv_ioctl.tv_sec, 
            (long int)tv_ioctl.tv_usec, error);
}
Run Code Online (Sandbox Code Playgroud)

printf语句的输出始终如下:

0.0错误= -1

错误= -1表示ioctl调用失败.我已经执行了测试getsockopt以检查是否设置了SO_TIMESTAMP选项,为SO_TIMESTAMP选项getsockopt返回0,因此它似乎正确设置.我在这里有点迷失,我怎么能进一步调查为什么ioctl调用似乎失败了?

eca*_*mur 5

用于检索套接字上最新时间戳的ioctl是SIOCGSTAMPSO_TIMESTAMP是套接字选项,而不是ioctl。您的代码应为:

int error = ioctl(fd, SIOCGSTAMP, &tv_ioctl);
                      ^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

检索时间戳的另一种方法是更改recvrecvmmsg辅助数据并从中提取时间戳。因为它涉及较少的系统调用(套接字读取和时间戳记),所以这效率更高。ioctl更简单。

请注意,SIOCGSTAMP和SO_TIMESTAMP是互斥的-如果要使用SIOCGSTAMP,则应禁用 SO_TIMESTAMP(带有enabled = 0)。这是因为SO_TIMESTAMP指示内核通过recvmmsg辅助数据而不是通过SIOCGSTAMP 使时间戳可用。

  • @Gio指示该套接字上没有可用的时间戳。您所做的工作显然没有错-也许尝试从内核文档https://www.kernel.org/doc/Documentation/networking/timestamping/timestamping.c运行时间戳记录示例,看看是否可以获得任何帮助工作。 (2认同)