-2

我有一个创建的 Windows 命名管道CreateFile(服务器端是使用创建的CreateNamedPipe)。我使用 IO 完成端口在两端异步读取/写入数据。

我需要在打开这些句柄后将它们发送给其他进程。我试图调用CloseHandle从返回的句柄CreateIoCompletionPort,然后在另一个进程中CreateIoCompletionPort再次调用。但是它总是失败并GetLastError返回 87 (ERROR_INVALID_PARAMETER )。

我也可以在一个过程中重现这一点,见下文。请注意,在我发送对象之前没有未完成的读/写操作。

std::wstring pipe_name = L"\\\\.\\pipe\\test.12345";
HANDLE server = CreateNamedPipeW(
    pipe_name.c_str(),
    PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
    1,
    4096,
    4096,
    10000,
    NULL);
SECURITY_ATTRIBUTES security_attributes = {
    sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
HANDLE client = CreateFileW(
    pipe_name.c_str(), GENERIC_READ | GENERIC_WRITE,
    0,
    &security_attributes,
    OPEN_EXISTING,
    SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED,
    NULL);
ULONG_PTR key = 1;
HANDLE comp_port = CreateIoCompletionPort(client, NULL, key, 1);

BOOL b1 = CloseHandle(comp_port);

comp_port = CreateIoCompletionPort(client, NULL, key, 1);
if (comp_port == NULL) {
  int last_err = GetLastError();
}
4

2 回答 2

2

参考CreateIoCompletionPort 的文档

一个句柄只能与一个 I/O 完成端口关联,并且在关联完成后,该句柄将一直与该 I/O 完成端口关联,直到它 [该句柄] 被关闭。

[...] I/O 完成端口句柄和与该特定 I/O 完成端口关联的每个文件句柄都称为对 I/O 完成端口的引用。I/O 完成端口在没有更多引用时被释放。

换句话说,关闭 I/O 完成端口句柄并不能实现任何目标。I/O 完成端口仍然存在并与管道句柄永久关联。您正在尝试的事情根本不可能;您将需要重新架构。

另请注意:

最好不要通过使用句柄继承或调用 DuplicateHandle 函数来共享与 I/O 完成端口关联的文件句柄。使用此类重复句柄执行的操作会生成完成通知。建议慎重考虑。

于 2015-08-28T00:36:25.023 回答
0

CreateIoCompletionPort的文档表明您尝试完成的任务是不可能的。与 I/O 完成端口关联的所有句柄都引用该端口,只要一个仍然打开,该端口就保持活动状态:

I/O 完成端口句柄和与该特定 I/O 完成端口关联的每个文件句柄都称为对 I/O 完成端口的引用。I/O 完成端口在没有更多引用时被释放。因此,必须正确关闭所有这些句柄以释放 I/O 完成端口及其关联的系统资源。满足这些条件后,调用CloseHandle函数关闭 I/O 完成端口句柄。

如果您使用 CreateFile 创建一个与 I/O 完成端口无关的新句柄,然后使用 DuplicateHandle 将其传递给其他进程,它应该可以工作。或者直接在其他进程中调用 CreateFile。

于 2015-08-28T00:31:56.710 回答