Используя pthread для создания одного потока, все записи на диск отправляются другими потоками? - PullRequest
0 голосов
/ 08 января 2020

Я сейчас пытаюсь создать программу, в которой несколько потоков запрашивают данные, которые необходимо обработать, а затем записать на диск. В настоящее время я использую прагму и критическую прагму, чтобы гарантировать, что данные записываются в соответствии с назначением.

Это довольно дорого, хотя потокам приходится ждать друг друга. Я прочитал, что должна быть возможность иметь единственную нить, обрабатывающую все записи на диски для вас, в то время как другие могут сосредоточиться на получении входящих данных и их анализе. Как мне go сделать это?

Программа представляет собой синтаксический анализатор пакетов на основе XDP, который хранит только конкретную информацию относительно каждого пакета. Код основан на этом коде проекта: https://github.com/xdp-project/xdp-tutorial/blob/master/tracing04-xdp-tcpdump/xdp_sample_pkts_user.c


    static int print_bpf_output(void *data, int size)
    {
        struct {
            __u16 cookie;
            __u16 pkt_len;
            __u8  pkt_data[SAMPLE_SIZE];
        } __packed *e = data;
        struct pcap_pkthdr h = {
            .caplen = SAMPLE_SIZE,
            .len    = e->pkt_len,
        };
        struct timespec ts;
        int i, err;

        if (e->cookie != 0xdead) {
            printf("BUG cookie %x sized %d\n",
                   e->cookie, size);
            return LIBBPF_PERF_EVENT_ERROR;
        }

        err = clock_gettime(CLOCK_MONOTONIC, &ts);
        if (err < 0) {
            printf("Error with gettimeofday! (%i)\n", err);
            return LIBBPF_PERF_EVENT_ERROR;
        }

        h.ts.tv_sec  = ts.tv_sec;
        h.ts.tv_usec = ts.tv_nsec / NANOSECS_PER_USEC;

        if (verbose) {
            printf("pkt len: %-5d bytes. hdr: ", e->pkt_len);
            for (i = 0; i < e->pkt_len; i++)
                printf("%02x ", e->pkt_data[i]);
            printf("\n");
        }

        pcap_dump((u_char *) pdumper, &h, e->pkt_data);
        pcap_pkts++;
        return LIBBPF_PERF_EVENT_CONT;
    }

Эта функция будет вызываться несколькими потоками, и я хочу, чтобы вызовы pcap_dump выполнялись одним, другая тема.

1 Ответ

1 голос
/ 09 января 2020

Да, это распространенный способ избежать задержек, когда диск достаточно быстр для обработки средней скорости передачи данных, но когда случайные пики данных, запись в кэш диска, обновления каталогов и другие подобные причины вызывают периодическую потерю данных.

Вам нужна очередь производитель-потребитель. Такой класс или код / ​​структура, использующие condvars или семафоры, легко найти в SO или в другом месте net. Очередь нуждается только в очереди указателей.

Не используйте широкую очередь для постановки в очередь массовых данных. Как только он будет прочитан из [где угодно], прочитайте его в неправильно распределенный буфер / структуру, в которой есть данные, путь, команда и все остальное, что потоку записи может понадобиться для выполнения записи. Поставьте в очередь указатель структуры на поток записи. В потоке записи l oop округляет всплывающую очередь P- C, получает указатели, выполняет запись (или все, что задано полем команды struct) и, если нет ошибок, освобождает struct. Если есть какая-то проблема, вы можете загрузить сообщение об ошибке в какое-то поле структуры и снова поставить его в очередь для какого-либо потока регистрации ошибок, сохранить его в очереди, чтобы повторить попытку позже, на самом деле.

Таким образом, вы изолируете остальную часть своего приложения от этих неизбежных, случайных задержек диска. Это очень важно для дисков с высокой задержкой, например. те в сети. Это также значительно упрощает вспомогательные операции, например, некоторый часовой таймер может поставить в очередь структуру, поле команды которой указывает потоку открыть новый файл с отметкой даты и времени в имени файла, что упрощает отслеживание данных позже без пробираясь через один массивный файл :) Такие операции, без очереди и потока записи, несомненно, вызовут огромную задержку для вашего приложения: (

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...