Named pipe in windows, difference between FILE_FLA

2019-07-30 18:22发布

问题:

I am using named pipe in windows and confused about the difference between FILE_FLAG_OVERLAPPED and PIPE_NOWAIT which are parameters set in CreateNamedPipe ,I set parameters like this.

HANDLE hPipe = CreateNamedPipe(
    lpszPipename,             // pipe name 
    PIPE_ACCESS_DUPLEX |      // read/write access 
    FILE_FLAG_OVERLAPPED,     // overlapped mode 
    PIPE_TYPE_MESSAGE |       // message-type pipe 
    PIPE_READMODE_MESSAGE |   // message read mode 
    PIPE_WAIT,                // blocking mode 
    PIPE_UNLIMITED_INSTANCES, // unlimited instances 
    BUFSIZE * sizeof(TCHAR),    // output buffer size 
    BUFSIZE * sizeof(TCHAR),    // input buffer size 
    PIPE_TIMEOUT,             // client time-out 
    NULL);                    // default security attributes

the ConnectNamedPipe return immediately and I get ERROR_IO_PENDING from GetLastError.With a nonblocking-wait handle, the connect operation returns zero immediately, and the GetLastError function returns ERROR_IO_PENDING.However the MSDN tells: With a nonblocking-wait handle, the connect operation returns zero immediately, and the GetLastError function returns ERROR_PIPE_LISTENING. so, what does nonblocking-wait mean, PIPE_NOWAIT or FILE_FLAG_OVERLAPPED, thanks a lot!

回答1:

PIPE_NOWAIT mean that Nonblocking mode is enabled on handle. In this mode, ReadFile, WriteFile, and ConnectNamedPipe always completed immediately.

the FILE_FLAG_OVERLAPPED mean asynchronous mode is enabled on handle. If this mode is enabled, all not synchronous io [1] operations always return immediately.

so FILE_FLAG_OVERLAPPED vs PIPE_NOWAIT - this is return immediately vs completed immediately.

completed immediately (which include return immediately ) mean that io operation is already completed when api return. but visa versa not true. if operation return immediately this not mean that operation is completed already. if operation still not completed ntapi return code STATUS_PENDING. win32 api in such situations usual set last error to ERROR_IO_PENDING.

exist 3 way determinate when io operation completed in case asynchronous handle mode.

  1. bind handle to IOCP (via CreateIoCompletionPort or BindIoCompletionCallback or CreateThreadpoolIo). as result when io complete - pointer to OVERLAPPED which we pass to io call - will be queued back to IOCP (in case BindIoCompletionCallback or CreateThreadpoolIo system yourself create IOCP and listen on it and call our registered callback, when pointer to OVERLAPPED will be queued to IOCP)
  2. some win32 api such ReadFileEx or WriteFileEx and all ntapi let specify APC completion routine which will be called in context of thread, which begin io operation, when io operation is completed. thread must do alertable wait in this case. this wait is not compatible with bind handle to IOCP (we can not use APC routine in api call if file handle binded to IOCP - system return invalid parameter error)
  3. we can create event and pass it to api call (via OVERLAPPED::hEvent) - in this case this event will be reset by system when io operation begin and set to signaled state when io operation is completed. unlike first 2 option in this case we have no additional context (in face pointer to OVERLAPPED) when io operation is completed. usually this is worst option.

[1] exist some io operations which is always synchronous api. for example GetFileInformationByHandleEx, SetFileInformationByHandle. but almost io operations is not synchronous io. all this io operations take pointer to OVERLAPPED as parameter. so if no pointer to OVERLAPPED in api signature - this is synchronous api call. if exist - usually asynchronous (exception CancelIoEx for example where pointer to overlapped is related not to current operation but to previous io operation which we want cancel). in particular ReadFile, WriteFile, DeviceIoControl, ConnectNamedPipe( internally this is call DeviceIoControl with FSCTL_PIPE_LISTEN) ) is not synchronous io api