16.1. 选择—awaitI/O 完成

此模块提供对大多数 os 中可用的select()poll()Function,Linux 2.5 上的epoll()和大多数 BSD 上的kqueue()的访问。请注意,在 Windows 上,它仅适用于套接字。在其他 os 上,它也适用于其他文件类型(特别是在 Unix 上,它适用于管道)。不能在常规文件上使用它来确定自上次读取文件以来文件是否已增长。

该模块定义以下内容:

  • exception select. error

    • 发生错误时引发的异常。随附的值是Pair,其中包含来自errno的数字错误代码和相应的字符串,如 C 函数perror()所打印的那样。
  • select. epoll([* sizehint = -1 *])

    • (仅在 Linux 2.5.44 和更高版本上受支持.)返回边缘轮询对象,可以将其用作 I/O 事件的边缘或级别触发接口。有关轮询对象支持的方法,请参见下面的边缘和水平触发轮询(epoll)对象部分。

2.6 版的新Function。

  • select. poll ( )

    • (并非所有 os 都支持.)返回一个轮询对象,该对象支持注册和注销文件 Descriptors,然后对它们进行轮询以获取 I/O 事件;有关轮询对象支持的方法,请参见下面的Polling Objects部分。
  • select. kqueue ( )

    • (仅在 BSD 上受支持.)返回内核队列对象;否则为 false。有关 kqueue 对象支持的方法,请参见下面的Kqueue Objects部分。

2.6 版的新Function。

  • select. kevent(* ident filter = KQ_FILTER_READ flags = KQ_EV_ADD fflags = 0 data = 0 udata = 0 *)
    • (仅在 BSD 上受支持.)返回内核事件对象;否则为 false。有关 kevent 对象支持的方法,请参见下面的Kevent Objects部分。

2.6 版的新Function。

  • select. select(* rlist wlist xlist * [,* timeout *])

    • 这是 Unix select()系统调用的直接接口。前三个参数是“await 对象”的序列:代表文件 Descriptors 的整数或具有名为fileno()的无参数方法的对象返回这样的整数:
    • rlist *:等到准备好阅读
    • wlist *:等到准备好写
    • xlist *:await“异常情况”(有关系统认为这种情况的信息,请参见手册页)

允许使用空序列,但是否接受三个空序列取决于平台。 (众所周知,它可以在 Unix 上工作,但不能在 Windows 上工作.)可选的* timeout 参数将超时指定为以秒为单位的浮点数。如果Ellipsis timeout *参数,该Function将阻塞直到至少一个文件 Descriptors 准备就绪。超时值为零表示轮询且永不阻塞。

返回值是准备好的对象列表的三倍:前三个参数的子集。在没有准备好文件 Descriptors 的情况下达到超时时,将返回三个空列表。

序列中可接受的对象类型包括 Python 文件对象(例如sys.stdinopen()os.popen()返回的对象),socket.socket()返回的套接字对象。您也可以自己定义* wrapper *类,只要它具有适当的fileno()方法(实际上返回文件 Descriptors,而不仅仅是随机整数)即可。

Note

Windows 上的文件对象是不可接受的,但套接字是可接受的。在 Windows 上,基础select()函数由 WinSock 库提供,并且不处理不是源自 WinSock 的文件 Descriptors。

  • select. PIPE_BUF
    • 报告为准备好pass此模块中的select()poll()或类似接口写入的文件,不会在写入PIPE_BUF个字节时阻塞。 POSIX 保证该值至少为 512.可用性:Unix。

2.7 版的新Function。

16.1.1. 边缘和水平触发轮询(epoll)对象

Note

http://linux.die.net/man/4/epoll

eventmask

ConstantMeaning
EPOLLIN可供阅读
EPOLLOUT可写
EPOLLPRI紧急数据读取
EPOLLERR错误状况发生在 assoc 上。 fd
EPOLLHUP挂断发生在 assoc 上。 fd
EPOLLET设置边缘触发行为,默认为电平触发行为
EPOLLONESHOT设置单发行为。撤消一个事件后,内部将禁用 fd
EPOLLRDNORM相当于EPOLLIN
EPOLLRDBAND可以读取优先数据带。
EPOLLWRNORM相当于EPOLLOUT
EPOLLWRBAND可以写入优先级数据。
EPOLLMSGIgnored.
  • epoll. close ( )

    • 关闭 epoll 对象的控制文件 Descriptors。
  • epoll. fileno ( )

    • 返回控件 fd 的文件 Descriptors 号。
  • epoll. fromfd(* fd *)

    • 从给定的文件 Descriptors 中创建一个 epoll 对象。
  • epoll. register(* fd * [,* eventmask *])

    • 向 epoll 对象注册 fdDescriptors。

Note

注册已注册的文件 Descriptors 会引发 IOError –与Polling Objects的注册相反。

  • epoll. modify(* fd eventmask *)

    • 修改寄存器文件 Descriptors。
  • epoll. unregister(* fd *)

    • 从 epoll 对象中删除注册的文件 Descriptors。
  • epoll. poll([* timeout = -1 * [,* maxevents = -1 *]])

    • await 事件。超时(以秒为单位)(Float)

16.1.2. 轮询对象

大多数 Unix 系统上支持的poll()系统调用为同时服务于许多 Client 端的 Web Service 器提供了更好的可伸缩性。 poll()具有更好的伸缩性,因为系统调用仅需要列出感兴趣的文件 Descriptors,而select()则构建位图,为感兴趣的 fds 打开位,然后再重新线性扫描整个位图。 select()是 O(最高文件 Descriptors),而poll()是 O(最高文件 Descriptors 数量)。

  • poll. register(* fd * [,* eventmask *])
    • 向轮询对象注册文件 Descriptors。然后,将来对poll()方法的调用将检查文件 Descriptors 是否具有任何未决的 I/O 事件。 * fd *可以是整数,也可以是具有返回整数的fileno()方法的对象。文件对象实现fileno(),因此它们也可用作参数。
  • eventmask *是可选的位掩码,用于描述您要检查的事件的类型,并且可以是下表中描述的常量POLLINPOLLPRIPOLLOUT的组合。如果未指定,则使用的默认值将检查所有 3 种类型的事件。
ConstantMeaning
POLLIN有要读取的数据
POLLPRI有紧急数据需要阅读
POLLOUT准备输出:写不会阻塞
POLLERR某种错误情况
POLLHUPHung up
POLLNVAL无效的请求:Descriptors 未打开

注册已经注册的文件 Descriptors 不是错误,并且与只注册一次 Descriptors 具有相同的效果。

  • poll. modify(* fd eventmask *)
    • 修改已注册的 fd。与register(fd, eventmask)具有相同的效果。try修改从未注册的文件 Descriptors 会导致IOError异常,出现 errno ENOENT

2.6 版的新Function。

  • poll. unregister(* fd *)
    • 删除轮询对象正在跟踪的文件 Descriptors。就像register()方法一样,* fd *可以是整数,也可以是具有fileno()方法的对象返回整数。

try删除从未注册的文件 Descriptors 会引发KeyError异常。

  • poll. poll([* timeout *])
    • 轮询已注册文件 Descriptors 的集合,并返回一个可能为空的列表,其中包含要报告事件或错误的 Descriptors 的(fd, event) 2Tuples。 * fd 是文件 Descriptors,而 event 是位掩码,其中为该 Descriptors 的报告事件设置了位-POLLINawaitImporting,POLLOUT表示可以写入 Descriptors,依此类推。空列表表示呼叫超时,并且没有文件 Descriptors 报告任何事件。如果指定了 timeout ,则它指定系统将在返回之前 await 事件的时间长度(以毫秒为单位)。如果Ellipsis timeout *,negative 或None,则该调用将阻塞,直到该轮询对象发生事件为止。

16.1.3. 队列对象

  • kqueue. close ( )

    • 关闭 kqueue 对象的控制文件 Descriptors。
  • kqueue. fileno ( )

    • 返回控件 fd 的文件 Descriptors 号。
  • kqueue. fromfd(* fd *)

    • 从给定的文件 Descriptors 创建一个 kqueue 对象。
  • kqueue. control(* changelist max_events * [,* timeout *])→事件列表

    • kevent 的低级接口
  • 变更列表必须是 kevent 对象或None的可迭代对象

  • max_events 必须为 0 或正整数

  • 超时(以秒为单位)(可能会 Float);默认值为None,以永远 await

16.1.4. Kevent 对象

https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2

  • kevent. ident

    • 用于标识事件的值。解释取决于过滤器,但通常是文件 Descriptors。在构造函数中,ident 可以是 int 或具有 fileno()函数的对象。 kevent 在内部存储整数。
  • kevent. filter

    • 内核过滤器的名称。
ConstantMeaning
KQ_FILTER_READ获取 Descriptors 并在有数据可读取时返回
KQ_FILTER_WRITE获取 Descriptors 并在有数据可写时返回
KQ_FILTER_AIOAIO requests
KQ_FILTER_VNODE返回在* fflag *中监视的一个或多个请求事件发生时返回
KQ_FILTER_PROC监视进程 ID 上的事件
KQ_FILTER_NETDEV监视网络设备上的事件[在 Mac OS X 上不可用]
KQ_FILTER_SIGNAL每当将观察到的 signal 传递到流程时返回
KQ_FILTER_TIMER构建一个任意计时器
  • kevent. flags
    • Filter action.
ConstantMeaning
KQ_EV_ADD添加或修改事件
KQ_EV_DELETE从队列中删除事件
KQ_EV_ENABLEPermitscontrol()返回事件
KQ_EV_DISABLEDisablesevent
KQ_EV_ONESHOT首次发生后删除事件
KQ_EV_CLEAR检索事件后重置状态
KQ_EV_SYSFLAGSinternal event
KQ_EV_FLAG1internal event
KQ_EV_EOF过滤特定的 EOF 条件
KQ_EV_ERROR查看返回值
  • kevent. fflags
    • 过滤特定标志。

KQ_FILTER_READKQ_FILTER_WRITE过滤器标志:

ConstantMeaning
KQ_NOTE_LOWAT套接字缓冲区的低水位线

KQ_FILTER_VNODE个过滤器标志:

ConstantMeaning
KQ_NOTE_DELETE* unlink()*被称为
KQ_NOTE_WRITE发生写
KQ_NOTE_EXTEND文件已扩展
KQ_NOTE_ATTRIB属性已更改
KQ_NOTE_LINK链接数已更改
KQ_NOTE_RENAME文件已重命名
KQ_NOTE_REVOKE对该文件的访问权已被撤消

KQ_FILTER_PROC个过滤器标志:

ConstantMeaning
KQ_NOTE_EXIT该过程已退出
KQ_NOTE_FORK该过程已调用* fork()*
KQ_NOTE_EXEC该流程执行了一个新流程
KQ_NOTE_PCTRLMASK内部过滤器标志
KQ_NOTE_PDATAMASK内部过滤器标志
KQ_NOTE_TRACK遵循跨* fork()*的过程
KQ_NOTE_CHILD在子进程上返回* NOTE_TRACK *
KQ_NOTE_TRACKERR无法依恋孩子

KQ_FILTER_NETDEV过滤器标志(在 Mac OS X 上不可用):

ConstantMeaning
KQ_NOTE_LINKUP链接已构建
KQ_NOTE_LINKDOWN链接已断开
KQ_NOTE_LINKINV链接状态无效
  • kevent. data

    • 过滤特定数据。
  • kevent. udata

    • 用户定义的值。