0

我制作了一个应用程序,它监视接口并每秒返回一个数据包读数,但在执行时它运行良好大约 30 秒,直到我打开一个 YouTube 页面让计数器运行得有点高。几秒钟后,应用程序冻结并且什么也不做。这发生在不规则的时间间隔内,所以我猜测它与计数有关,有代码,它是用 C 编写的。

#include <stdio.h>
#include <pcap.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <pthread.h>

void callThreads(u_char *useless, const struct pcap_pkthdr* pkthdr, const u_char* packet);
void *packetcalc(void *threadid);

static struct timespec time1, time2;
static int t = 0, i = 0;
static long rc;
static pthread_t threads[1];

int main(int argc, char *argv[]){

    pcap_t* descr;
    char errbuf[PCAP_ERRBUF_SIZE];


    descr = pcap_open_live("eth0", BUFSIZ, 1, -1, errbuf);

    if(descr == NULL){
        printf("Error: pcap_open_live()\n");
        return 1;
    }
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
    pcap_loop(descr, 0, callThreads, NULL);
    return 0;
}

void callThreads(u_char *useless, const struct pcap_pkthdr* pkthdr, const u_char* packet){
    if(i >= 2147483647){
        //In case i gets full from counting too many packets        
        i = 0;
        time1.tv_sec = 0;
    }

    ++i;
    rc = pthread_create(&threads[t], NULL, packetcalc, (void *) t); 
}

void *packetcalc(void *threadid){

    static int j;
    static int temp = 0;

    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
    if(temp != time1.tv_sec){
        j = (i / time1.tv_sec);
        printf("Packets: %d/sec\t(%d)\t(%d)\n", j, i, (int)time1.tv_sec);
        temp = time1.tv_sec;
    }


    pthread_exit(NULL);
}

编辑:是否也可能是我在一个由于多线程而只分配了 1 个 CPU 的 VM 中运行此代码?

4

2 回答 2

2

您正在为每个数据包创建一个线程,这是一个可怕的想法。只需从您提供的回调函数中打印出您需要的任何计数器就足够了pcap_loop(3)

于 2012-12-10T13:16:24.920 回答
1

您的代码有几个问题。首先,您使用默认线程属性创建线程,这意味着它们被创建为可连接线程,即您必须pthread_join()稍后调用,否则线程控制结构将继续存在。因此,您的代码中存在内存泄漏。可能您应该检查返回值pthread_create以检测何时发生错误,例如系统无法创建新线程并且您的数据包计数例程已停止调用。您还可以使用以下代码创建处于分离状态的新线程:

pthread_attr_t attr;

pthread_attribute_init(&attr);
pthread_attribute_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

pthread_create(&threadid, &attr, packetcalc, (void *) t);

pthread_attribute_destroy(&attr);

分离的线程不需要稍后加入。他们在线程退出时释放所有资源。

其次,您的线程使用一些全局变量,就好像它们是私有的,而实际上它们是共享的。这包括全局的time1,以及局部的jtemp,它们被声明static并因此在线程之间共享。

请注意,创建线程是一项昂贵的操作。当您的代码等待pthread_create完成时,新数据包可能会到达并填满由 使用的循环缓冲区,libpcap因此您可能会丢失一些数据包。事实上,每个数据包使用一个线程是一个非常糟糕的主意。而是只使用两个线程 - 一个运行pcap循环,另一个定期计算数据包数量并计算和打印数据包速率。

于 2012-12-10T12:53:39.773 回答