1

我使用 libpcap 捕获数据包,一旦数据包可用,我需要将数据包放入 FIFO 队列。但是 FIFO 队列是由 2 个线程共享的,一个线程调用 pcap_next() 并将数据包放入 FIFO 队列。另一个线程从 fifo 队列中获取数据包。所以我必须将它与互斥锁相关联。如下所示:

u_char* pkt;
for(;;){
    pkt = pcap_next();
    lock(&mutex);
    some_process(pkt);
    insert(pkt, list);
    unlock(&mutext);
 }

pcap_next() 与数据包缓冲区有关,如果缓冲区中没有数据包,则阻塞 pcap_next()。如果有数据包,则每次调用 pcap_next() 都会返回 1 个数据包。

它只能为每个锁定-解锁操作对获取一个数据包,如果数据包到达不频繁,则可以。但是如果报文到达频繁,比如缓冲区中有很多待处理的报文,那么为一个报文做一个lock-unlock操作对有点耗费资源。

我希望的是:处理并插入数据包后,我立即可以检查数据包缓冲区中是否有可用的数据包。如果有,继续处理和插入。否则,解锁互斥锁并返回循环。

有解决方法吗?

4

2 回答 2

1

尝试诸如

/*
 * XXX - this can fail on some platforms and with some devices,
 * and there may be issues with select() on this.  See the
 * pcap_get_selectable_fd() man page for details.
 */
pcap_fd = pcap_get_selectable_fd(p);
pcap_setnonblock(p);  /* XXX - check for failure */

for (;;) {
    fd_set fdset;
    struct timeval timeout;

    /*
     * Wait for a batch of packets to be available.
     */
    FD_ZERO(&fdset);
    FD_SET(pcap_fd, &fdset);
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    if (select(1, &fdset, NULL, NULL, &timeout) == -1) {
        report an error;
    } else {
        lock(&mutex);
        pcap_dispatch(p, -1, callback, pointer-to-stuff);
        unlock(&mutex);
    }
}

这样,您锁定互斥体,处理整批数据包,然后解锁互斥体。许多操作系统捕获机制以一批方式传送多个数据包,因此在这种情况下,每批都会有一个锁定/解锁对。

回调会做的some_process(pkt);事情insert(pkt, list);

有可能,一旦你完成了一个批次,下一个批次将立即可用,因此这并没有达到锁定/解锁对的绝对最小值;但是,绝对最小值可能会在很长一段时间内锁定另一个线程,因此它永远无法取得任何进展,因此锁定和解锁每个批次可能是最好的。

于 2015-03-26T21:07:16.473 回答
0

只需使用 pcap_dispatch() 或 select() 与非阻塞样式 pcap_next()

于 2013-05-14T16:22:52.147 回答