Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is Non-Blocking IO implemented?

In Java or C# or some other languages, there are non-blocking IO facilities, e.g., for sockets.

So I can give my callback functions to the non-blocking IO and once the non-blocking IO receives anything, it will call my callbacks.

I am wondering how they are implemented. If I create non-blocking IO, behind the scene, does Java or C# just create background threads for them? or the OS underlying has native support for them?

like image 771
Jack Avatar asked May 10 '12 16:05

Jack


1 Answers

On Windows there is underlying OS support for non-blocking I/O, and Microsoft's CLR takes advantage of that. Other CLR implementations (mono) probably do as well, but I don't know for sure. When performing async I/O on the Microsoft CLR there is not a 1-to-1 correlation between pending async I/O operations and threads (or at least managed threads) waiting for those I/O operations to complete.

See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365683(v=vs.85).aspx for some details on the Win32-layer details. Also the information on I/O completion ports here: http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx

My understanding is this:

  1. I begin an async I/O operation on some application thread.
  2. If it hasn't already, a queue will be created (well, really a kernel-level construct called an I/O completion port, which is associated with a queue in the kernel space of my application). In the .NET world a specially designated thread called an I/O completion port thread will start waiting for notifications of I/O completion on that queue. The important thing to note here is that I can make any number of async I/O requests without increasing the number of I/O completion ports.
  3. The OS will notify the application when I/O completes by enqueueing an I/O completion message on the queue. The I/O completion port thread will then handle that message by invoking the I/O completion callback in my .NET application. In the meantime, if other I/O completes, it's results will be enqueued behind the currently-processing results.

Caveats to the above:

  1. I am sure I got part of this wrong, but I believe the overall gist of it is correct. Eric or someone can come in and correct me where I'm off.

  2. In .NET there are multiple I/O completion port threads. I have no idea how async I/O requests are allocated amongst the various I/O completion ports. This may be an operating system feature (wherein I/O may come back on any port that the application has open).

For Java I am sure it depends on the JVM implementation and the particular OS. I don't know it nearly well enough to speculate beyond that.

EDIT: Historical update, many more details here

like image 193
Chris Shain Avatar answered Oct 23 '22 09:10

Chris Shain