分类:
2012-07-31 13:21:11
原文地址:第十四章*高级I/O(六)--异步I/O 作者:yourtommy
使用select和poll,如前一节所述的,是一个同步形式的通知。系统不告诉我们任何事,直到我们问(通过select或poll的调用)。如 我们在第10章看到的,信号提供了一个异步形式的通知,当某些事发生时。所有从BSD和系统V继承的系统提供一些形式的异步I/O,使用一个信号(系统V 上的SIGPOLL;BSD上的SIGIO)来通知进程一些感兴趣的东西在一个描述符上发生出。
我们看到select和poll工作于任何描述符上。但是使用异步I/O,我们现在碰到限制。在从系统V继承的系统上,异步I/O只工作在STREAMS设备和STREAMS管道。在BSD继承的系统上,异步I/O只工作于终端和网络。
异步I/O的一个限制是一个进程只有一个信号。如果我们为异步I/O开启多个描述符,我们不能知道哪个描述符对应于被分发的信号。
SUS包含了一个可选的通用异步I/O机制,从实时草稿标准中采纳。这和我们在这里描述的机制无关。这个机制解决了许多存在于早期异步I/O机制的限制,但是我们不再更深讨论它。
14.6.1 系统V异步I/O
在系统V,异步I/O是STREAMS系统的一部分,并只工作在STREAMS设备和STREAMS管道上。系统V异步I/O信号是SIGPOLL。
为了给一个STREAMS设备启用异步I/O,我们必须调用第二个参数(request)为I_SETSIG的ioctl。第三个参数是一个整型值,由下表的一个或多个常量组成。这些常量定义在
常量 | 描述 |
---|---|
S_INPUT | 一个不是高优先级消息的消息到达。 |
S_RDNORM | 一个普通消息到达。 |
S_RDBAND | 一个非0优先带宽消息到达。 |
S_BANDURG | 如果常量由S_RDBAND指定,SIGURG信号代替SIGPOLL产生,当非0优先带宽消息到达时。 |
S_HIPRI | 一个高优先级消息到达。 |
S_OUTPUT | 写队列不再满。 |
S_WRNORM | 和S_OUTPUT一样。 |
S_WRBAND | 我们可以发送非0优先带宽消息。 |
S_MSG | 包含SIGPOLL信号一个STREAMS信号消息到达。 |
S_ERROR | 一个M_ERROR消息到达。 |
S_HANGUP | 一个M_HANGUP消息到达。 |
除了调用ioctl来指定应该产生SIGPOLL信号的情况,我们还必须为这个信号建立一个信号处理机。回想第10章SIGPOLL的默认动作是终止进程,所以我们应该在调用ioctl之前设立这个信号处理机。
14.6.2 BSD异步I/O
BSD后代系统里的异步I/O是两个信号的组合:SIGIO和SIGURG。前者是通用异步I/O信号,而后者只用来通知超过带宽的数据在一个网络连接上到达。
为了接收SIGIO信号,我们需要执行三个步骤。
1、设立一个SIGIO的信号处理机,通过调用signal或sigaction。
2、设置描述符信号的进程ID或进程组ID,通过用一个F_SETOWN命令调用fcntl(3.14节)。
3、在描述符上启用异步I/O,通过用命令F_SETFL调用fcntl来设置O_ASYNC文件状态标志。
步骤3只可以在指向终端或网络的描述符上执行,它是BSD异步I/O设施的基本限制。
对于SIGURG信号,我们只需要执行步骤1和步骤2。SIGURG只为指向支持带宽外数据的网络连接的描述符产生。