In general, it is well known that I/O management can be one of the messiest aspects of an operating system. I/O devices can be of various kinds i.e. either human readable (e.g. printers) , machine readable (e.g. disks, sensors)or for communication purposes (e.g. wired or wireless modems of various sorts, home routers etc.). All these devices are different in terms of data rate, unit of transfer (streams of bytes or blocks of characters), data representation etc. So, it is difficult to develop some uniform and consistent theory which covers every case and aspect. Also, as is widely known, the ways we can do I/O are programmed I/O, Interrupt-driven I/O and Direct Memory Access (DMA). Each of these has advantages and drawbacks depending on various factors.
I/O often forms a bottleneck in a computer system as I/O devices are slow (or very slow) compared with processor and main memory. One solution is multiprogramming, as it allows some processes waiting for I/O while others are running. So, we have a more efficient management of resources, but alone does not solve the above mentioned problem. There are still issues to be solved regarding the I/O efficiency. Disk operations is one very important of them.
During the years, I/O devices have become - and of course still do, faster and more efficient but an also important issue is providing a uniform and efficient way in handling them. One good strategy for this is hiding most of the details of device I/O in lower-level routines, so that processes and upper levels see devices in general terms such as read, write, etc. So, a layered I/O software system can serve this purpose, having layers (top to bottom): I/O user-level software, OS software (device independent) , Device Drivers, Interrupt Handlers, Hardware.
Also, buffering (single or double) is an important technique in order to avoid deadlocks among processes.
Now, above, I just briefly described a strategy for a system using interrupt driven I/O. For a system using DMA things go in a different way, as DMA module utilizes the system bus in order to transfer data and suspends the processor at some point. The net effect is delaying the processor to some degree. The importance of this effect really depends on the quantity of data, as for a multi-word transmission, DMA is far more efficient than interrupt driven I/O. But on the other hand, given today's very fast processors with multi cores, extremely efficient pipelining they are using etc., interrupt-driven I/O is far less of an issue than it was in the past.
There is a plenty of resources all over the net about multiprogramming in operating systems, which can be very easily found through google.