UNIX advanced IO

同步IO和异步IO

IO操作一般分成两个不同的阶段:

  1. 等待数据准备好
  2. 从内核向进程复制数据

比如说对于网络IO:

  1. 第一步通常是等待数据从网络中到达,然后复制到内核中的某个缓冲区。
  2. 把数据从内核缓冲区复制到应用进程缓冲区。

比如说对于系统调用read:

  1. 内核把数据在内核缓冲区中准备好。
  2. 然后把它复制到进程IO缓冲区。

而对于标准IO来说,还多了一个标准IO缓冲区。它们的设置是为了减少调用erad和write的次数。

同步IO操作导致请求进程阻塞,直到IO完成为止。在同步IO中,真正的IO操作会阻塞进程。不管是阻塞IO还是非阻塞IO,以及IO多路复用,信号驱动的IO模型,都是同步IO。
异步IO操作不导致请求进程阻塞,即使真正的IO操作也不会阻塞。相对于信号驱动的IO,内核通知我们的是什么时候可以启动一个IO操作,而异步IO模型是内核通知我们IO操作什么时候完成。

阻塞IO

所有的套接字都是阻塞的。从数据复制到内核,以及从内核复制到应用程序缓冲区,都是阻塞的。

非阻塞IO

非阻塞IO的意思是告诉内核如果当前的操作如果不能立即返回,而是要sleep才能完成时,返回一个错误。
等到某一次查询,数据已经准备了,然后进行相应的IO操作。

select和poll,epoll

IO复用模型的思想是同时处理多个文件描述符。

select和pselect

selecdt返回的条件:

  1. 等待的描述符准备好(读准备好,写准备好,异常准备好)只有两个异常的条件。
  2. 超时

满足任意一个就行。

poll

epoll

信号驱动的IO

利用信号,让内核在描述符就绪时发送SIGIO通知应用程序,然后调用相应的处理程序进行IO操作。

异步IO

内核把数据准备好,然后复制到应用程序缓冲区之后才通知我们。这个时候IO操作已经完成了。

记录锁

记录锁可以用来同步。打开一个空文件,使用第一个字节作为锁字节。要访问资源,需要对该字节加锁,要释放资源,需要对该字节解锁。
所以一个文件可以实现多个锁。

readv和writev

readv从文件描述符指定的文件中读取相应的数据到多个缓冲区。
writev将多个缓冲区中的内容写入文件描述符中。

readn和writen

适用于已经知道要读取和写入的字节数量的情景。其实就是多次调用非阻塞的read和write进行操作。

存储映射IO

mmap将一个磁盘文件映射到存储空间的一个缓冲区上。从缓冲区读,就相当于读文件中的相应字节。从缓冲区写,就相当于写文件中的相应字节。

参考文献

1.《APUE》第三版
2.《UNP》卷一