本文介绍了PACKET_MMAP的一些问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用packet_mmap读取UDP数据包的快速流.使用以下任一代码段等待传入的帧时,效果很好:

I'm using packet_mmap to read a fast stream of UDP packets. When using either of the following code segments to wait for incoming frames it works fine:

// ring[i].iov_base points to the start address of the ith frame
struct tpacket_hdr *header = (struct tpacket_hdr *) ring[i].iov_base;

// Using poll on socket to wait for data
while(!(header -> tp_status & TP_STATUS_USER))
    {
        struct pollfd pfd;
        pfd.fd      = _socket;
        pfd.events  = POLLIN | POLLERR;
        pfd.revents = 0;
        poll(&pfd, 1, -1);
    }

// Using nanosleep to wait for incoming data
while(!(header -> tp_status & TP_STATUS_USER))
    {
        struct timespec t, r;
        t.tv_nsec = 1;
        t.tv_sec = 0; 
        nanosleep(&t, &r)
    }

但是,当我尝试忙于等待时(while(!(header -> tp_status & TP_STATUS_USER)) ;,在读取了几个数据包后,该语句将无限期保持为True.这是为什么呢?内核仅在发出系统调用时才将帧传输到环形缓冲区吗?输入套接字初始化为:socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)).

However when I try to busy wait (while(!(header -> tp_status & TP_STATUS_USER)) ; the statement remains True indefinitely after a few packets are read. Why is this so? Does the kernel only transfer frames to the ring buffer when a system call is issued? The input socket is initialised as so: socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)).

此外,在使用此代码(使用poll或nanosleep)时,它似乎正在丢弃数据包,而使用UDP套接字的简单接收代码却没有,这使得packet_mmap的实现速度变慢.有时套接字会检测到丢弃的数据包,但是当对getsockopt使用PACKET_STATISTICS选项时:

Also, when using this code (using poll or nanosleep) it seems to be dropping packets, whilst a simple receive code using a UDP socket doesn't, making the packet_mmap implementation slower. Sometimes the dropped packets are detected by the sockets, however when using the PACKET_STATISTICS option to getsockopt:

    if (header -> tp_status & TP_STATUS_LOSING)
    {
        struct tpacket_stats stats;
        socklen_t size_sock = sizeof(tpacket_stats);
        if (getsockopt(_socket, SOL_PACKET, PACKET_STATISTICS, &stats, &size_sock) > -1)
            printf("Dropped packets: [%d, %d]\n", stats.tp_drops, stats.tp_packets);
    }

它声明没有数据包被丢弃(输出示例:已丢弃的数据包:[0,5]"). PACKET_STATISTICSPACKET_RX_RING套接字上的行为是否有所不同?

it states that no packets were dropped (output example: "Dropped packets: [0, 5]"). Does PACKET_STATISTICS behave differently on PACKET_RX_RING sockets?

此代码的完整代码列表可用这里

The full code listing for this code is available here

推荐答案

以防万一有人遇到此问题,繁忙等待正在挂起",因为tpacket_hdr已优化并存入寄存器,并且未在内存中检查其值.将其标记为volatile可确保应用程序看到内核对此结构所做的任何更改.

Just in case someone encounters this issue, busy waiting was "hanging" because tpacket_hdr was being optimized and into registers and it's value not checked in memory. Marking this as volatile ensures that any changed made by the kernel to this structure are seen by the application.

使用PACKET_STATISTICS检测到的数据包丢失是针对接收到的前几个数据包,其余的是由于应用程序由于系统调用引起的额外开销而无法跟上传入的数据包.

The packet drops detected with PACKET_STATISTICS were for the first few packets which were being received, and the rest were due to the application not keeping up with the incoming packets because of the extra overhead caused by the system calls.

这篇关于PACKET_MMAP的一些问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 23:40