0

我有一个带有 1 个生产者线程和 N 个消费者线程的程序。产品有N种类型,所以我设置了N个FIFO队列(产品应该按顺序交付给消费者)。如:FIFO_queue_t* fifo_queque[N]。

如果 FIFO 队列中没有产品,消费者线程将被阻塞/等待。所以对于消费者线程i,他们这样做:

        for(;;)
        {
            sem_wait(&sem[i]);
            product = fetch_one_product(queue);
            process(product);
         }

对于生产者,它在将产品用于线程i放入 FIFO queue时调用 sem_post(&semp[i]) i

在我看来,在这种情况下我必须使用 N 个信号量,如果 N 很大,则资源消耗很大。我的想法有什么遗漏吗?

更新

 The system is like a proxy, and my original design is like this:

我有一个监听端口的 tcp 服务器listen(listenfd, 20)

生产者是一个 libpcap 实例,它从该端口捕获 TCP 数据包,产品是捕获数据包(包括 IP/TCP 头);

对于每个 connfd=accept(listenfd)。我创建了一个负责这个 connfd 的线程。这些线程是消费者。

我创建了一个查找表,每个条目中的字段是:

1 source IP/PORT, source address of incoming TCP connection,
2 FIFO Queue pointer: the fifo queue of captured spacket
3 pthread id :  the thread that is responsible for a tcp connection

当生产者线程获取数据包时,它会从数据包中解析源 IP/PORT,查找表,定位 FIFO 队列并将其放入 FIFO 队列。

当消费者线程收到通知其 FIFO 队列中有一些数据包时,它会从队列中获取数据包。特别是对于最初的 3-way 数据包:TCP SYN、SYN/ACK 和 ACK,它需要维护一些状态信息,如 MSS、SACK 等,并且还需要将这些数据包(包括 TCP/IP 头)作为UDP 有效载荷,并将 UDP 数据包发送到其他一些远程主机。

4

1 回答 1

1

这似乎是一个无法很好扩展的设计。如果您有 1,000 种不同的产品,那么您将有 1,000 个不同的 FIFO 队列、1,000 个信号量和 1,000 个线程在运行。这几乎是不可能管理的。

最好使用单个队列和少量线程。线程可以处理任何类型的项目。您唯一的困难是将物品按顺序交付给客户,但这通常不是问题。为了解决这个问题,您需要做的就是添加某种序列号,这样当一件物品即将发送给客户时,您检查序列号并等待它是否不是您期望的序列号。

当然,您实际上并没有等待,而是将项目放入被阻塞的输出队列中,等待正确的项目进入。如果您可以保证线程不会崩溃并丢弃项目,这将非常有效. 因为如果发生这种情况,您的客户的输出将停止。你需要某种策略来防止永久阻塞:也许是一个超时,它说:“好吧,我等了够久了。即使它出了问题,客户也会得到这个项目。”

添加以回应评论:

所以你有一个由生产者填充的输入队列,少量的消费者线程,每个线程都可以处理任何类型的产品,然后是 N 个输出队列(这似乎过多),或者一个带有溢出的输出队列以允许用于缓冲乱序项。我假设您有少量线程(也许只有一个?)为输出队列提供服务并将项目发送给客户。

出现故障的物品只能在溢出中停留很短的时间。它们在那里是因为两个(或更多)相同类型的项目非常接近地出队,并且后者在较早的项目之前完成了处理。这应该是一个罕见的事件,所以你的溢出桶根本不应该很大。您可以轻松地使溢出成为一个简单的列表,并按顺序对其进行扫描,而不会造成明显的性能损失。

于 2013-05-14T17:40:39.647 回答