Winapi 如何为句柄重新注册IO完成端口

Winapi 如何为句柄重新注册IO完成端口,winapi,pipe,port,named,completion,Winapi,Pipe,Port,Named,Completion,我有一个名为pipe的Windows,我使用CreateFile创建它(服务器端是使用CreateNamedPipe创建的)。我使用IO完成端口在两端异步读/写数据 打开这些句柄后,我需要将它们发送到其他进程。我试图对从CreateIoCompletionPort返回的句柄调用CloseHandle,然后在另一个进程中再次调用CreateIoCompletionPort。但是它总是失败,GetLastError返回87(ERROR\u INVALID\u参数) 我也可以在一个过程中重现这一点,见

我有一个名为pipe的Windows,我使用
CreateFile
创建它(服务器端是使用
CreateNamedPipe
创建的)。我使用IO完成端口在两端异步读/写数据

打开这些句柄后,我需要将它们发送到其他进程。我试图对从
CreateIoCompletionPort
返回的句柄调用
CloseHandle
,然后在另一个进程中再次调用
CreateIoCompletionPort
。但是它总是失败,
GetLastError
返回87(
ERROR\u INVALID\u参数

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

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();
}
的文档表明您试图实现的目标是不可能的。与I/O完成端口关联的所有句柄都指向该端口,只要有一个句柄仍然打开,该端口就会保持活动状态:

I/O完成端口句柄和与该特定I/O完成端口关联的每个文件句柄称为对I/O完成端口的引用。当不再有对I/O完成端口的引用时,将释放该端口。因此,必须正确关闭所有这些句柄才能释放I/O完成端口及其相关的系统资源。满足这些条件后,通过调用CloseHandle函数关闭I/O完成端口句柄

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

参考:

一个句柄只能与一个I/O完成端口关联,关联完成后,句柄将保持与该I/O完成端口的关联,直到它[句柄]关闭

[…]I/O完成端口句柄和与该特定I/O完成端口关联的每个文件句柄称为对I/O完成端口的引用。当不再有对I/O完成端口的引用时,将释放该端口

换句话说,关闭I/O完成端口句柄不会实现任何效果。I/O完成端口仍然存在,并与管道句柄永久关联。你所尝试的是不可能的;你需要重新架构

另请注意:

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


好主意,我试着在合上把手之前复制它,但这似乎保留了一个参考。我担心再次调用CreateFile,因为如果发送另一端,则可能导致管道的两侧都被关闭。在第一个客户端句柄和完成端口上调用CloseHandle之前,我尝试了第二次调用CreateFile。CreateFile返回无效的\u句柄\u值,GetLastError为管道\u错误\u忙碌。即使我将nMaxInstances更改为PIPE_UNLIMITED_实例,这种情况仍在发生。根据MSDN,我尝试了循环并调用WaitNamedPipe,但没有解决问题。@johnsef:PIPE\u ERROR\u BUSY通常是由于服务器端未能调用ConnectNamedPipe造成的。服务器必须调用ConnectNamedPipe吗?我不认为它和第一个CreateFile成功很好。我的问题是,我不知道在服务器上调用它的频率,因为它不知道客户端何时切换进程。我终于让它工作了,我没有意识到我必须为每个实例调用CreateNamedPipe一次。感谢您的帮助。看起来服务器-客户端句柄对具有单独的数据视图。我只寻找一个视图,即使我将句柄发送到不同的进程,因此调用CloseHandle也不会起作用。感谢您的回复,我在上面对我尝试在关闭句柄之前调用CreateFile的想法进行了评论。您是对的,看起来这在IOCP中是不可能的。