pcap dispatch - обработка обратного вызова вопросы
Я пишу довольно просто PCAP" live " capture engine, однако реализация обратного вызова обработки пакетов для pcap_dispatch должна занять относительно много времени для обработки. Запускает ли pcap каждый обратный вызов "pcap_handler" в отдельном потоке? Если да, является ли" pcap_handler " потокобезопасным, или следует позаботиться о его защите критическими разделами? Кроме того, не pcap_dispatch callback работает в серийное мода? Е. Г. это "pcap_handler" для пакетов 2 только после того, как "pcap_handler" для пакета 1 производится? Если да, то существует ли подход, позволяющий избежать накопления латентности? Спасибо, - V
1 ответов
Pcap в основном работает следующим образом: существует драйвер режима ядра, который захватывает пакеты и помещает их в буфер размера B. Приложение пользовательского режима может запросить любое количество пакетов в любое время с помощью pcap_loop
, pcap_dispatch
или pcap_next
(последнее в основном pcap_dispatch
С одного пакета).
поэтому, когда вы используете pcap_dispatch
, чтобы запросить какие-то пакеты, libpcap идет к ядру и запрашивает следующий пакет в буфере (Если нет одного кода тайм-аута, и материал запускается, но это не имеет значения для этого обсуждения), передает его в userland и удаляет его из буфера. После этого, pcap_dispatch
вызывает обработчик, уменьшает его пакеты-к - счетчик и начинается с самого начала. В результате pcap_dispatch
возвращает только если запрошенное количество пакетов было обработано, произошла ошибка или тайм-аут.
Как видите, libpcap полностью без резьбы,как и большинство C API. Однако драйвер режима ядра, очевидно, достаточно счастлив, чтобы доставлять пакеты нескольким потокам (иначе вы не смогли бы захватить более одного процесса) и полностью потокобезопасен (для каждого дескриптора usermode есть один отдельный буфер).
это означает, что вы должны реализовать все параллелизмы самостоятельно. Вы бы хотели сделать что-то вроде этого:
pcap_dispatch(P, count, handler, data);
.
.
.
struct pcap_work_item {
struct pcap_pkthdr header;
u_char data[];
};
void handler(u_char *user, struct pcap_pkthdr *header, u_char *data)
{
struct pcap_work_item *item = malloc(sizeof(pcap_pkthdr) + header->caplen);
item->header = *header;
memcpy(item->data, data, header->caplen);
queue_work_item(item);
}
обратите внимание, что мы должны скопировать пакет в кучу, потому что the header
и data
указатели недействительны после возврата обратного вызова.
функции queue_work_item
должен найти рабочий поток и назначить ему задачу обработки пакета. Поскольку вы сказали, что ваш обратный вызов занимает "relativley долгое время", вам, вероятно, понадобится большое количество рабочих потоков. Поиск подходящего числа работников подвергается тонкой настройке.
в начале этого сообщения я сказал, что драйвер режима ядра имеет буфер для сбора входящих пакетов которые ждут обработки. Размер этого буфера определяется реализацией. The до pcap_open_live
только контролирует, сколько байтов одного пакета захвачено, однако, пакетов нельзя контролировать портативным способом. Он может быть фиксированного размера. Он может увеличиваться по мере поступления все большего количества пакетов. Однако,если он переполняется, все дальнейшие пакеты отбрасываются, пока не будет достаточно места для следующего. Если вы хотите использовать ваш приложение в среде с высоким трафиком необходимо убедиться, что обратный вызов* pcap_dispatch * выполняется быстро. Мой пример обратного вызова просто назначает пакет работнику, поэтому он отлично работает даже в условиях высокого трафика.
надеюсь, это ответит на все ваши вопросы.