0

インターフェイスを監視し、1秒あたりのパケット数の読み取り値を返すアプリケーションを作成しましたが、実行すると、YouTubeページを開いてカウンターを少し高くするまで、約30秒間正常に実行されます。数秒後、アプリケーションはフリーズし、何もしません。これは不規則な間隔で発生するので、Imはカウントで何かを推測し、コードがあり、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);
}

編集:マルチスレッドのためにCPUが1つしか割り当てられていない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);

切り離されたスレッドは後で結合する必要はありません。スレッドの終了時にすべてのリソースを解放します。

第二に、実際には共有されている場合でも、スレッドはいくつかのグローバル変数をプライベートであるかのように使用します。これには、 globaltime1と localjおよびが含まれますtemp。これらは宣言されstaticているため、スレッド間で共有されます。

スレッドの作成はコストのかかる操作であることに注意してください。コードが完了するのを待っている間にpthread_create、新しいパケットが到着し、 によって使用される循環バッファがいっぱいにlibpcapなる可能性があるため、一部のパケットが失われる可能性があります。実際のところ、パケットごとに 1 つのスレッドを使用するのは非常に悪い考えです。代わりに、2 つのスレッドのみを使用します。1 つはpcapループを実行し、もう 1 つは定期的にパケット数をカウントし、パケット レートを計算して出力します。

于 2012-12-10T12:53:39.773 に答える