2012-12-10 71 views
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?

+0

纯粹的猜测:你需要在得到一个数据包后释放一些缓冲区或其他资源,而你没有这样做,并且pcap对于保留缓冲区有一些内部最大值。 IOW:阅读文档或一些示例代码,搜索一个函数来执行某种自由/释放/清理操作。 – hyde

回答

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循环,一个定期统计数据包数量并计算并打印数据包速率。

2

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

相关问题