Question

High-level languages often expose stream-based I/O abstraction to the programmer, where blocking or non-blocking streams offer select/read/write operations. (AFAIK, message-based I/O seems is usually an even higher-level abstraction built on top of streams.)

But at the low level, the communication between the CPU and the hardware devices uses interrupts, programmed (polled) I/O, or DMA.

How can all of them map well into the same stream I/O abstraction that (as far as I can tell) completely hides the difference between these very different low-level models? Are there any cases where a high-level developer who uses stream I/O abstraction should actually be concerned about the difference between interrupt-driven and programmed I/O?

Was it helpful?

Solution

Interrupt based IO does not map to streams well.

One particular example would be a select system call. It provides a way to wait for input on arbitrary count of file descriptors but this API almost never manifests in stream API of high level libraries

Asynchronous IO also does not map to usual streams. This is why role of streams diminishes in modern libraries and gives way to more generic event driven APIs, for example C++ boost::asio, Java NIO. They are more effective for asynchronous and parrallel applications and are a reaction for growing parallelization demand.

Note however, that internally, most of these APIs are still using same system interfaces still based on interrupts and good old buffers. It is possible, because libraries are still hiding details behind layers of abstractions.

BTW, all these abstractions (streams,events,buffered IO) are interchangeable at expense of some performance. For example, streams can be created using events with some blocking queues, backward conversion could be provided by dedicated thread.

Licensed under: CC-BY-SA with attribution
scroll top