Blocking - process suspended until I/O completed
Easy to use and understand
Insufficient for some needs
Nonblocking - I/O call returns as much as available
User interface, data copy (buffered I/O)
Implemented via multi-threading
Returns quickly with count of bytes read or written
select() to find if data ready then read() or write() to transfer
Asynchronous - process runs while I/O executes
Difficult to use
I/O subsystem signals process when I/O completed