我正在使用packet_mmap读取UDP数据包的快速流。当使用下列代码段,以等待数据帧正常工作。PACKET_MMAP的一些问题
// 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)) ;
的声明仍然是正确了几包被读取后无限期为什么会这样呢?当系统调用发出时内核只传输帧到环形缓冲区?输入套接字被初始化为:socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))
此外,当使用此代码(使用poll或nanosleep)时,它似乎丢弃数据包,而使用UDP套接字的简单接收代码不会使packet_mmap实现变慢,有时丢弃的数据包会被套接字检测到,但是当使用PACKET_STATISTICS
选项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_RX_RING
插座上的行为有所不同吗?
完整的代码此代码清单,请here