When I run this program
OVERLAPPED o;
int main()
{
..
CreateIoCompletionPort(....);
for (int i = 0; i<10; i++)
{
WriteFile(..,&o);
OVERLAPPED* po;
GetQueuedCompletionStatus(..,&po);
}
}
it seems that the WriteFile didn't return until the writing job is done. At the same time , GetQueuedCompletionStatus() gets called. The behavior is like a synchronous IO operation rather than an asynch-IO operation.
Why is that?
If the file handle and volume have write caching enabled, the file operation may complete with just a memory copy to cache, to be flushed lazily later. Since there is no actual IO taking place, there's no reason to do async IO in that case.
Internally, each IO operation is represented by an IRP (IO request packet). It is created by the kernel and given to the filesystem to handle the request, where it passes down through layered drivers until the request becomes an actual disk controller command. That driver will make the request, mark the IRP as pending and return control of the thread. If the handle was opened for overlapped IO, the kernel gives control back to your program immediately. Otherwise, the kernel will wait for the IRP to complete before returning.
Not all IO operations make it all the way to the disk, however. The filesystem may determine that the write should be cached, and not written until later. There is even a special path for operations that can be satisfied entirely using the cache, called fast IO. Even if you make an asynchronous request, fast IO is always synchronous because it's just copying data into and out of cache.
Process monitor, in advanced output mode, displays the different modes and will show blank in the status field while an IRP is pending.
There is a limit to how much data is allowed to be outstanding in the write cache. Once it fills up, the write operations will not complete immediately. Try writing a lot of data at once, with may operations.
I wrote a blog posting a while back entitled "When are asynchronous file writes not asynchronous" and the answer was, unfortunately, "most of the time". See the posting here: http://www.lenholgate.com/blog/2008/02/when-are-asynchronous-file-writes-not-asynchronous.html
The gist of it is:
For security reasons Windows extends files in a synchronous manner
You can attempt to work around this by setting the end of the file to a large value before you start and then trimming the file to the correct size when you finish.
You can tell the cache manager to use your buffers and not its, by using FILE_FLAG_NO_BUFFERING
At least it's not as bad as if you're forced to use FILE_FLAG_WRITE_THROUGH
If GetQueuedCompletionStatus is being called, then the call to WriteFile is synchronous (and it has returned), but it can still modify &o even after it's returned if it is asynchronous.
from this page in MSDN:
For asynchronous write operations,
hFile can be any handle opened with
the CreateFile function using the
FILE_FLAG_OVERLAPPED flag or a socket
handle returned by the socket or
accept function.
also, from this page:
If a handle is provided, it has to
have been opened for overlapped I/O
completion. For example, you must
specify the FILE_FLAG_OVERLAPPED flag
when using the CreateFile function to
obtain the handle.
Related
The WaitNamedPipe function allows a pipe client application to synchronously wait for an available connection on a named pipe server. You then call CreateFile to open the pipe as a client. Pseudocode:
// loop works around race condition with WaitNamedPipe and CreateFile
HANDLE hPipe;
while (true) {
if (WaitNamedPipe says connection is ready) {
hPipe = CreateFile(...);
if (hPipe ok or last error is NOT pipe busy) {
break; // hPipe is valid or last error is set
}
} else {
break; // WaitNamedPipe failed
}
}
The problem is that these are all blocking, synchronous calls. What is a good way to do this asynchronously? I can't seem to find an API that uses overlapped I/O to do this, for example. For example, for pipe servers the ConnectNamedPipe function provides an lpOverlapped parameters allowing for a server to asynchronously wait for a client. The pipe server can then call WaitForMultipleObjects and wait for the I/O operation to complete, or any other event to be signaled (for example, an event signaling the thread to cancel pending I/O and terminate).
The only way I can think of is to call WaitNamedPipe in a loop with a short, finite timeout and check other signals if it times out. Alternatively, in a loop call CreateFile, check other signals, and then call Sleep with a short delay (or WaitNamedPipe). For example:
HANDLE hPipe;
while (true) {
hPipe = CreateFile(...);
if (hPipe not valid and pipe is busy) {
// sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout
Sleep(100);
// TODO: check other signals here to see if we should abort I/O
} else
break;
}
But this method stinks to high heaven in my opinion. If a pipe isn't available for awhile, the thread continues to run - sucking up CPU, using power, requiring memory pages to remain in RAM, etc. In my mind, a thread that relies on Sleep or short timeouts does not perform well and is a sign of sloppy multi-threaded programming.
But what's the alternative in this case?
WaitNamedPipe is completely useless, and will just use all the cpu if you specify a timeout and there's no server waiting for it.
Just call CreateFile over and over with a Sleep like you're doing, and move it to other threads as you see appropriate. There is no API alternative.
The only "benefit" WaitNamedPipe provides is if you want to know if you can connect to a named pipe but you explicitly don't want to actually open a connection. It's junk.
If you really want to be thorough, your only options are
Ensure that whatever program is opening the named pipe is always calling CreateNamedPipe again immediately after it's named pipe is connected to.
Have your program actually check if that program is running.
If your intent is really not to have additional connections, still call CreateNamedPipe, and when someone connects, tell them to go away until they're waited a given amount of time, the close the pipe.
Why can't the server just create more pipes? The performance hit in the scenario you describe isn't a problem if it is rare.
I.e. if there are usually enough pipes to go round what does it matter if you use CreateFile/Sleep instead of WaitForMultipleObjects? The performance hit will not matter.
I also have to question the need for overlapped IO in a client. How many servers is it communicating with at a time? If the answer is less than, say, 10 you could reasonably create a thread per connection.
Basically I am saying I think the reason there is no overlapped WaitforNamedPipe is because there is no reasonable use-case which requires it.
You can open the pipe file system at \\.\pipe\ and then use DeviceIoControl to send FSCTL_PIPE_WAIT.
I have a legacy code which is doing this:
select(nFD + 1, &tReadFds, NULL, NULL, &timer);
.............
if (FD_ISSET(nFD, &tReadFds))
n = read(nFD,len,x);
is the read gonna read the whole receive buffer(nFD), assuming 'len' and 'x' are big enough.
I think SELECT here is acting as just a way of blocking till data becomes available in recv buffer.
In a nutshell, select is a function that you can call without blocking (i.e. it returns immediately), and upon return it will tell you a list of file descriptors on which you can call read (or write) without blocking.
Such a function is crucial if you want to provide a persistent service while processing I/O with only a single thread: You cannot afford to do nothing while you are waiting for I/O, and so you need a deterministic method to ensure that you can do non-blocking I/O.
Edit. Here's an example of a typical single-threaded select-server, in pseudo-code:
while (true)
{
select(...);
read_available_data();
process_data_and_do_work(); // expensive
}
Such a server never has to be idle, and the expensive processing function can take up almost all the available computing time (it just has to make sure to return when it needs more data). I think select even allows for a context switch, so this will play nice in a multi-process environment.
The code snippet is calling select() with a non-NULL timeout parameter. The code is waiting up to some maximum amount of time for the socket to become readable. If the timeout elapses, the socket is not readable and FD_ISSET() will return false, skipping the read() call. However, if the socket becomes readable before the timeout elapses, FD_ISSET() will return true, and a call to read() is quaranteed not to block the calling thread. It will return immediately, either returning whatever data is currently in the socket's receive buffer (up to len bytes max), or returning 0 if the remote party has disconnected gracefully.
I use next code to know when a files is changed in a certain folder:
HANDLE hDir = ::CreateFile(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL);
FILE_NOTIFY_INFORMATION returnData[1024];
DWORD returnDataSize = 0;
while(ReadDirectoryChangesW(hDir, returnData, sizeof(returnData), TRUE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_LAST_WRITE, &returnDataSize, NULL, NULL))
{
...
}
ReadDirectoryChangesW blocks the thread until a file changes occurs. Is there any way to stop/force return from this function?
From your description, it sounds like CancelIoEx should do the trick. Obviously, you need another thread for that, since you're now calling it synchronously. That blocks the calling thread, so you can't do anyting from that thread, not even stop.
I think you need to take a look at this blog post: http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html
It's a lengthy post, but it's very informative and it talks about all the issues associated with this method.
You need to call this API function in its asynchronous mode of operation. You achieve this, as with many other file APIs, by passing an OVERLAPPED struct to the API call.
When you operate asynchronously the function will return immediately and it's up to you when you choose to collect the results. You can test whether or not the function is ready to supply results, you can opt to be notified that the API has results available, you can cancel the pending I/O, and you can choose to block until results are available. There is an awful lot of flexibility and naturally the API is more complex to use in asynchronous mode.
There is lots of information on MSDN about overlapped I/O. Start here: Synchronization and Overlapped Input and Output.
If you want the blocking call to return from another thread, change something that will make the call return - create a temporary file, perhaps.
Is there a way to check the number of bytes available from a USB device (printer in our case)?
We're using CreateFile and ReadFile and WriteFile for IO communications with our USB device, which works. But We can't figure out how much data is available without actually doing a read. We can't use GetFileSize, as even the documentation says you can't use it for a :
"nonseeking device such as a pipe or a communications device"...
So that doesn't work. Any suggestions? Are we doing our USB I/O incorrectly? Is there a better way to Read/Write to USB?
You first need to open up the port in asynchronous mode. To do that, pass the flag FILE_FLAG_OVERLAPPED to CreateFile. Then, when you call ReadFile, pass in a pointer to an OVERLAPPED structure. This does an asynchronous read and immediately returns ERROR_IO_PENDING without blocking (or, if the OS already has the data buffered, you might get lucky and get a successful read -- be prepared to handle that case).
Once the asynchronous I/O has started, you can then periodically check if it has completed with GetOverlappedResult.
This allows you to answer the question "are X bytes of data available?" for a particular value of X (the one passed to ReadFile). 95% of the time, that's good enough, since you're looking for data in a particular format. The other 5% of the time, you'll need to add another layer of abstraction top, where you keep doing asynchronous reads and store the data in a buffer.
Note that asynchronous I/O is very tricky to get right, and there's a lot of edge cases to consider. Carefully read all of the documentation for these functions to make sure your code is correct.
Can you use C#? If so you can access the USB port using System.IO.SerialPort class, and then set up a DataReceived event handler for incoming data. There is a BytesToRead property that tells you how much data is waiting to be read.
All of this must be available in native code, if I can find it I'll edit this.
EDIT: the best I can find for native is ReadPrinter - I don't see how to check if data is there, this will block if it's not.
One can use poll/select when writing a server that can service multiple clients all in the same thread. select and poll, however need a file descriptor to work. For this reason, I am uncertain how to perform simple asynchronous operations, like implementing a simple callback to break up a long running operation or a delayed callback without exiting the select/poll loop. How does one go about doing this? Ideally, I would like to do this without resorting to spawning new threads.
In a nutshell, I am looking for a mechanism with which I can perform ALL asynchronous operations. The windows WaitForMultipleObjects or Symbian TRequestStatus seems a much more suited to generalized asynchronous operations.
For arbitrary callbacks, maintain a POSIX pipe (see pipe(2)). When you want to do a deferred call, write a struct consisting of a function pointer and optional context pointer to the write end. The read end is just another input for select. If it selects readable, read the same struct, and call the function with the context as argument.
For timed callbacks, maintain a list in order of due time. Entries in the list are structs of e.g. { due time (as interval since previous callback); function pointer; optional context pointer }. If this list is empty, block forever in select(). Otherwise, timeout when the first event is due. Before each call to select, recalculate the first event's due time.
Hide the details behind a reasonable interface.
select() and poll() are syscalls - it means that your program is calling OS kernel to do something and your program can do nothing while waiting for return from kernel, unless you use other thread.
Although select() and poll() are used for async I/O, these functions (syscalls) are not async - they will block (unless you specify some timeout) until there is something happened with the descriptor you are watching.
Best strategy would be to check descriptors time to time (specifying small timeout value), and if there is nothing, do what you want to do in idle time, otherwise process I/O.
You could take advantage of the timeout of select() or poll() to do your background stuff periodically:
for ( ;; ) {
...
int fds = select(<fds and timeout>);
if (fds < 0) {
<error occured>
} else if if (fds == 0) {
<handle timeout, do some background work.>
} else {
<handle the active file descriptors>
}
}
For an immediate callback using the select loop, one can use one of the special files like /dev/zero that are always active. The will allow select the exit soon but will allow other files to become active as well.
For timed delays, I can only thing of using the timeout on select.
Both of the above don't feel great, so please send better answers.