Winapi 如何为句柄重新注册IO完成端口
我有一个名为pipe的Windows,我使用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参数) 我也可以在一个过程中重现这一点,见
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中是不可能的。