关闭 AF_PACKET 与 AF_INET 的时间差?

Posted

技术标签:

【中文标题】关闭 AF_PACKET 与 AF_INET 的时间差?【英文标题】:Time difference of closing AF_PACKET vs AF_INET? 【发布时间】:2019-05-21 10:41:56 【问题描述】:

关闭创建为AF_PACKETAF_INET 的套接字之间的时间差的原因是什么?如何减少AF_PACKET 的关闭时间?

sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
close(sockfd); // 60000 μs

sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
close(sockfd); // 30 μs

重现行为的代码:

#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

#include <sys/socket.h>
#include <net/if.h>

int main() 
    struct timeval time_start, time_end;
    int sockfd;

    if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) 
        perror("socket error");
     

    gettimeofday(&time_start, NULL);
    close(sockfd);
    gettimeofday(&time_end, NULL);
    printf("close AF_PACKET: %ld \n", (time_end.tv_sec*1000000 + time_end.tv_usec) - (time_start.tv_sec*1000000 + time_start.tv_usec));


    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) 
        perror("socket error");
     

    gettimeofday(&time_start, NULL);
    close(sockfd);
    gettimeofday(&time_end, NULL);
    printf("close AF_INET: %ld \n", (time_end.tv_sec*1000000 + time_end.tv_usec) - (time_start.tv_sec*1000000 + time_start.tv_usec));

    return 0;

【问题讨论】:

无法复制;如果你展示一个完整的测试用例会有所帮助。 @mosvy ,我粘贴了源代码以重现该行为。 RPi 和笔记本电脑也有同样的问题。 用 linux 3.4.52 试过:`close AF_PACKET: 168 close AF_INET: 94` 使用 linux 4.4.34:close AF_PACKET: 324 close AF_INET: 91. 【参考方案1】:

两个 close 系统调用在逻辑上没有显着差异

如果我像下面这样更改您的程序,

`

int main() 
    struct timeval time_start, time_end;
    int sockfd;

    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) 
        perror("socket error");
       

    gettimeofday(&time_start, NULL);
    close(sockfd);
    gettimeofday(&time_end, NULL);
    printf("close AF_INET: %ld \n", (time_end.tv_sec*1000000 + time_end.tv_usec) - (time_start.tv_sec*1000000 + time_start.tv_usec));

    if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) 
        perror("socket error");
       

    gettimeofday(&time_start, NULL);
    close(sockfd);
    gettimeofday(&time_end, NULL);
    printf("close AF_PACKET: %ld \n", (time_end.tv_sec*1000000 + time_end.tv_usec) - (time_start.tv_sec*1000000 + time_start.tv_usec));

    return 0;
`

我看到的结果是

shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 3471 
close AF_PACKET: 4 
shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 8 
close AF_PACKET: 7 
shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 8 
close AF_PACKET: 6 
shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 8 
close AF_PACKET: 5 
shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 9 
close AF_PACKET: 5 

同样的,如果我改变如下,

int main() 
    struct timeval time_start, time_end;
    int sockfd;

    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) 
        perror("socket error");
    

    gettimeofday(&time_start, NULL);
    close(sockfd);
    gettimeofday(&time_end, NULL);
    printf("close AF_INET: %ld \n", (time_end.tv_sec*1000000 + time_end.tv_usec) - (time_start.tv_sec*1000000 + time_start.tv_usec));

    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) 
        perror("socket error");
     

    gettimeofday(&time_start, NULL);
    close(sockfd);
    gettimeofday(&time_end, NULL);
    printf("close AF_INET: %ld \n", (time_end.tv_sec*1000000 + time_end.tv_usec) - (time_start.tv_sec*1000000 + time_start.tv_usec));

    if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) 
        perror("socket error");
       

    gettimeofday(&time_start, NULL);
    close(sockfd);
    gettimeofday(&time_end, NULL);
    printf("close AF_PACKET: %ld \n", (time_end.tv_sec*1000000 + time_end.tv_usec) - (time_start.tv_sec*1000000 + time_start.tv_usec));



    return 0;

结果如下,

shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 6 
close AF_INET: 3 
close AF_PACKET: 3 
shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 8 
close AF_INET: 4 
close AF_PACKET: 5 
shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 8 
close AF_INET: 4 
close AF_PACKET: 4 
shahul@shahul-VirtualBox:~/test$  ./a.out 
close AF_INET: 8 
close AF_INET: 4 
close AF_PACKET: 4 

结论: 基本上,第一次近距离通话需要更多时间, 可能需要时间来映射第一次关闭系统调用函数

【讨论】:

感谢您的回复。不幸的是,我无法确认我的设备:Raspberry Pi (Raspbian 9.4. 4.14.17) 和笔记本电脑 (Ubuntu 17.04, 4.10.0)。即使经过多次开闭循环,收盘时间差异也保持不变。

以上是关于关闭 AF_PACKET 与 AF_INET 的时间差?的主要内容,如果未能解决你的问题,请参考以下文章

使用ctypes和python并调用libc accept时的EFAULT

以太网校验和是不是通过 AF_PACKET 暴露?

suricata抓包方式之一 AF_PACKET

CVE-2016-8655,af_packet Linux 內核通殺提權漏洞淺析

socket编程

python:UDP网络程序与总结