linux 设备驱动程序 (6) – 阻塞型 io、poll
阻塞型 IO
上篇的例子中, 当资源不可获取时 (读写指针指向同一个位置) 我们提到了采取阻塞的方式. 这一篇展开叙述阻塞 io.
在用户态程序中, 调用进程通常只会简单的调用 read 和 write, 不会考虑数据是否可用, 输出缓冲区是否已满之类的问题. 在我们的驱动程序中, 当遇见这种情况应当 [默认] 阻塞该进程, 直到数据可用.
但在这之前, 先来讨论一下 unix 中的 io 模型. unix 中的 io 大概包括以下几类:
- 阻塞型 IO
- 非阻塞型 IO
- 异步 IO
关于异步 IO 及异步通知机制在下一篇中讲述. 这一篇关注驱动程序如何处理阻塞型 IO 和非阻塞型 IO 的问题.
非阻塞型 io 语义
非常简单, 当数据不可用时, read/write 函数返回 EAGAIN. 所以我们的驱动程序只需当数据不可用时返回 - EAGAIN 即可
阻塞型 IO 语义
这是 unix 中最常见的的 IO. 对于阻塞型 IO 语义的总结如下:
对于从设备读取数据:
- 如果缓冲区中有数据, 并且驱动程序可以保证数据可以很快到达 (难以察觉的延迟), 那么即使就绪的数据比请求的少 read 函数也应返回
- 如果缓冲区中无数据, 默认下 read 应当阻塞等待直到至少一个字节到达
- 如果缓冲区中无数据, 并且设置了 O_NONBLOCK 标志, read 应立即返回 - EAGAIN
- 如果缓冲区中无数据, poll 函数必须报告设备不可读, 直到至少一个字节到达
- 如果到达文件尾, read 应立即返回 0, 无论 O_NONBLOCK 标志
- 如果到达文件尾, poll 应报告 POLLHUP
对于向设备写入数据:
- 如果输出缓冲区中有空间, write 应立即返回即使可接收的数据比请求的数据少
- 如果缓冲区已满, 默认下 write 应阻塞等待直到有空间被释放
- 如果缓冲区已满, 并且设置了 O_NONBLOCK 标志, write 应立即返回 - EAGAIN
- 如果缓冲区已满, poll 函数应报告文件不可写
- 如果设备不能再接受任何数据, write 应返回 - ENOSPC
- 不要在 write 中等待数据传输完成 [既数据传输到真正的硬件中]write 函数只需保证数据可靠写入输出缓冲区中
- 如果使用设备的程序必须保证数据写入硬件, 则驱动必须提供 fsync 函数
[未完]