A key concept within the design of I/O software is understood as device independence. It means I/O devices should be accessible to programs without specifying the device beforehand.
Uniform Naming, purely either be a string or an integer and not be contingent on the device in any manner. In UNIX, all disks are often integrated within the file-system hierarchy in arbitrary ways therefore the user needn't remember of which name corresponds to which device.
Error Handling: If the controller discovers a read error, it should attempt to correct the error itself if it can. If it cannot, then the driver should handle it, perhaps by just trying to read the block again. In many cases, error recovery are often done transparently at a coffee level without the upper levels even knowing about the error.
Synchronous (blocking) and Asynchronous (interrupt-driven) transfers: Most physical I/O is asynchronous, however, some very high-performance applications got to control all the small print of the I/O, so some operating systems make asynchronous I/O available to them.
Buffering: Frequently information that come off a machine cannot be saved immediately in their final objective.
Sharable and dedicated devices: Some I/O devices, like disks, are often employed by many users at an equivalent time. No problems are caused by multiple users having open files on an equivalent disk at an equivalent time. Other devices, like printers, need to be dedicated to one user until that user is finished. Then another user can have the printer. Introducing dedicated (unshared) devices also introduces a spread of problems, like deadlocks. The OS should be prepared to manage equally shared and dedicated devices during a way which avoids difficulties.