gpt4 book ai didi

iocp - 如果 I/O 完成端口数据包可能以不同的顺序出列,为什么 I/O 完成端口数据包按 FIFO 顺序排队?

转载 作者:行者123 更新时间:2023-12-05 01:02:47 27 4
gpt4 key购买 nike

Microsoft 的 I/O Completion Ports 文档状态:

Please note that while the [completion] packets are queued in FIFO order they may be dequeued in a different order.

据我了解,线程通过调用GetQueuedCompletionStatus从完成端口获取完成包。 .如果系统不保证数据包将按 FIFO 顺序检索,为什么系统会按 FIFO 顺序将数据包排队到完成端口?

最佳答案

您引用的语句旨在让您意识到,如果需要在单个套接字上的 I/O 完成之间进行排序,则需要进行自己的排序。如果您在单个套接字上发出多个 WSARecv 调用,您可能需要这个。当它们完成时,完成将按 FIFO 顺序进入 IOCP 队列,这将是发出 WSARecv 调用的顺序。

如果您继续阅读该文档,您将看到这篇文章:

Threads that block their execution on an I/O completion port are released in last-in-first-out (LIFO) order, and the next completion packet is pulled from the I/O completion port's FIFO queue for that thread. This means that, when a completion packet is released to a thread, the system releases the last (most recent) thread associated with that port, passing it the completion information for the oldest I/O completion.

这表明完成以 FIFO 顺序从 IOCP 中删除。第一个注释的原因是,如果您有多个线程在 IOCP 上等待,那么线程调度问题可能意味着您的代码处理完成的顺序与从 IOCP 中检索它们的顺序不同。

假设您有 2 个线程服务于一个 IOCP 和一个带有 3 个 WSARecv 待处理的 TCP 套接字。足够的数据来自网络以完成所有三个待处理的 WSARecv,因此您最终在 IOCP 中完成了三个;我们将它们称为 A、B 和 C。这些是发出 WSARecv 调用的顺序,因此应处理缓冲区 A、B 和 C 中的数据,以保持 TCP 流的健全性。

您的第一个 IOCP 线程将完成 A。第二个线程将完成 B。取决于您的硬件(内核数量等)和 OS 调度程序,线程 1 或线程 2 可能接下来会运行或者两者可以同时运行。这可能会导致您在上述情况下出现问题。

我个人通过在编写可以在单个套接字上发出多个 WSARecvs 的服务器时向每个缓冲区添加一个序列号来解决这个问题。序列号递增,插入缓冲区并在同一个锁内发出 WSARecv,因此整个操作是原子的。当完成发生时,我确保只有一个线程处理给定套接字的缓冲区(参见 here),或者我使用“序列缓冲区集合”,它可以确保以正确的顺序处理缓冲区(参见 here) .

还要注意,为了确保正确性,您需要锁定在给定套接字上发出 WSARecv(和 WSASend)调用(见 here)

关于iocp - 如果 I/O 完成端口数据包可能以不同的顺序出列,为什么 I/O 完成端口数据包按 FIFO 顺序排队?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27955812/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com