c - 使用 pthread 让一个线程执行其他线程发送的所有磁盘写入操作?

标签 c linux multithreading io pthreads

我现在正在尝试创建一个程序,其中多个线程正在查询需要处理然后写入磁盘的数据。目前,我正在使用 pragma 和 pragma critical 来确保数据按预期写入。

这是相当昂贵的,因为线程必须互相等待。我读到应该可以让一个线程为您处理所有对磁盘的写入,而其他线程可以专注于获取传入数据并解析它。我该如何去做呢?

该程序是一个基于 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 调用由单个不同的线程执行。

最佳答案

是的,这是避免延迟的常见方法,其中磁盘速度足以处理平均数据速率,但偶尔的数据峰值、磁盘缓存写入、目录更新等会导致间歇性数据丢失。

您需要一个生产者-消费者队列。这样的类或代码/结构,使用 condvars 或信号量,很容易在 SO 或网络上的其他地方找到。队列只需要对指针进行排队即可。

不要使用宽队列来对批量数据进行排队。一旦从[任何地方]读取它,就将其读入一个分配的缓冲区/结构,其中包含数据、路径、命令以及写入线程执行写入可能需要的任何其他内容。将指向写入线程的结构指针排队。在写入线程中,循环 P-C 队列弹出,获取指针,执行写入(或结构命令字段命令的任何操作),如果没有错误,则释放该结构。如果出现问题,您可以将错误消息加载到结构的某个字段中,然后将其再次排队到某个错误记录线程,将其存储在队列中以便稍后重试,无论您想要什么,真的。

这样,您就可以将应用程序的其余部分与那些不可避免的、偶尔的磁盘延迟隔离开来。这对于高延迟磁盘非常重要,例如。那些在网络上的。它还使内务操作变得更加容易,例如,一些小时计时器可以对一个结构进行排队,该结构的命令字段指示线程打开一个文件名中带有日期时间戳的新文件,因此可以更轻松地跟踪数据,而无需费力地浏览一个巨大的文件:)这种没有队列和写入线程的操作肯定会给您的应用程序造成巨大的延迟:(

关于c - 使用 pthread 让一个线程执行其他线程发送的所有磁盘写入操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59653491/

相关文章:

c - C 上的 libmongoc-1.0.pc/MongoDB 出现问题

c - 如何用0结束循环?

multithreading - 在 Node 模块中使用集群

C# .NET 异步 Web 服务

c++ - 与 boost::condition_variable 的线程同步

c - 为什么 *list++ 或 *(list++) 对 list[4] 不起作用,但对分配了 list 值的指针却能正常工作?

c - 如何在C中制作一个fifo特殊文件?

linux - 没有信号量的交替

linux - 递归遍历Samba共享?

linux - Cron 运行 .sh 文件没有任何结果