fp_select 内核服务

用途

提供对选择或轮询请求的级联支持或重定向支持。

语法

#include <sys/types.h> #include <sys/errno.h> int fp_select ( FP, 事件, 特内文特普, 通知) struct 文件 *FP; 乌斯霍特 事件; 乌斯霍特 *特内文特普; (*通知)();

参数

描述
Fp 指向要对其执行低级别选择操作的设备驱动程序,套接字或管道的开放式实例。
事件 用于标识要检查的事件。 为 轮询选择 函数定义了三个标准事件标志,并定义了一个参考标志。 /usr/include/sys/poll.h 文件详细描述了事件位定义。 四个基本指标是:
POLLIN
对于指定的对象,存在输入。
POLLOUT
所指定文件对象能够接受输出。
POLLPRI
在指定的对象上发生异常条件。
POLLSYNC
这仅是同步请求。 如果所请求的事件都不为 true ,那么所选例程不应将此请求记住为暂挂。 即,由于此请求,该例程不需要调用 塞尔通知 服务。
尔特内文特普 指示返回的事件指针。 此参数是通过引用传递的,用于指示当前时间哪些选定事件为 true。 返回的事件位包括请求的事件以及其他错误事件指示符:
POLLERR
该对象的选择例程指示了错误条件。 如果设置了此标志,那么来自指定对象的选择例程的非零返回码将作为来自 fp_select 内核服务的返回码返回。
notify 指向当指定的对象针对未完成的异步选择或轮询事件请求调用 塞尔通知 内核服务时要调用的例程。 如果不调用任何例程,那么此参数必须为 NULL。

描述

fp_select 内核服务是由内核扩展使用的低级服务,用于对开放式设备,套接字或命名管道执行选择操作。 可以将 fp_select 内核服务同时用于同步和异步选择请求。 同步请求报告设备的当前状态,并且异步请求允许向调用者通知设备上的未来事件。

从设备驱动程序的 ddselect 例程进行调用

设备驱动程序的 ddselect 例程可以调用 fp_select 内核服务以将选择/轮询请求传递到其他设备驱动程序。 一个设备的 ddselect 例程将调用 fp_select 内核服务,该内核服务将调用另一个设备的 ddselect 例程,以此类推。 当原始设备的事件信息依赖于其他设备上发生的事件时,此参数是必需的。 可以启动包含两个以上设备的选择请求的级联链,或者单个设备可以向其他几个设备发出 fp_select 调用。

每个 ddselect 例程在其对 fp_select 内核服务的调用中都应该保留它在先前由 fp_select 内核服务调用时接收到的同一 POLLSYNC 指示符。

从设备驱动程序外部进行调用的 ddselect 例程

如果 fp_select 内核服务是在设备驱动程序的 ddselect 例程之外调用的,那么 fp_select 内核服务会设置 POLLSYNC 标志,始终使请求同步。 在此情况下,不会发生指定设备的未来事件的通知,也不会调用 通知 例程 (如果已指定)。 fp_select 内核服务可以通过此方式 (与正在进行的轮询或选择请求无关) 使用来检查对象的当前状态。

通知例程的异步处理和使用

对于异步请求, fp_select 内核服务允许其调用者注册 通知 例程,以便在指定事件变为 true 时内核调用该例程。 当相关设备驱动程序检测到一个或多个暂挂事件变为 true 时,它将调用 塞尔通知 内核服务。 然后, 塞尔通知 内核服务会调用 通知 例程 (如果已注册)。 因此, 通知 例程在中断时调用,并且必须进行编程才能在中断环境中运行。

通知 例程的使用会影响中断时的调用顺序以及实际报告所请求信息的方式。 通用异步处理会产生以下事件序列:

  1. 选择请求在设备上启动,并通过多个 fp_select 内核服务调用传递到其他设备。 最终,将访问不依赖于其他设备的设备驱动程序的 ddselect 例程以获取信息。 此 ddselect 例程发现所有请求的事件都不为 true ,但会记住异步请求并返回到调用者。 这样,整个呼叫链就被回退了,直到到达选择请求的原点。 然后内核将原始进程置于休眠状态。
  2. 稍后,对于记住异步请求的设备,一个或多个事件变为 true。 设备驱动程序例程 (可能是中断处理程序) 调用 塞尔通知 内核服务。
  3. 如果事件仍在等待,那么 塞尔通知 内核服务将通过以下两种方式之一进行响应。 如果在对设备发出选择请求时未注册任何 通知 例程,那么将唤醒所有正在等待此设备上的事件的进程。 如果该设备存在 通知 例程,那么将调用此例程。 通知 例程确定是否应将原始请求的事件报告为 true ,如果报告为 true ,那么将自行调用 塞尔通知 内核服务。

以下示例详细描述了涉及多个设备的级联方案。 假设已针对设备 A 发出请求,并且设备 A 依赖于设备 B ,而设备 B 依赖于设备 C。当指定的事件在设备 C 变为 true 时,从设备 C 的设备驱动程序调用的 塞尔通知 内核服务会根据请求时是否注册了 通知 例程而执行不同的操作。

在不使用通知例程的情况下进行级联处理

如果未从设备 B 注册任何 通知 例程,那么 塞尔通知 内核服务将确定对于级联链的头处的设备驱动程序,指定的事件将被视为 true。 (链的头 (在本例中为设备 A) 是第一个从 fp_select 内核服务的选择例程发出该服务的设备驱动程序。) 塞尔通知 内核服务唤醒所有正在等待设备 A 上发生的事件的进程。

请务必注意,如果未使用任何 通知 例程,那么调用链中向 塞尔通知 内核服务报告事件的任何设备驱动程序都会导致该事件对于链中的第一个设备显示为 true。 因此,等待在该第一个设备上发生的事件的任何进程都将被唤醒。

具有通知例程的级联处理

另一方面,如果 通知 例程已在整个链中注册,那么每个中断设备 (通过调用 塞尔通知 内核服务) 都将在调用链中对其上方的设备调用 通知 例程。 因此,在前面的示例中,设备 C 的 塞尔通知 内核服务调用在设备 B 的 ddselect 例程调用 fp_select 内核服务时注册的 通知 例程。 然后,设备 B 的 通知 例程必须决定是否再次调用 塞尔通知 内核服务以向设备 A 的 通知 例程发出警报。 如果是这样,那么将调用设备 A 的 通知 例程,并自行确定是否调用另一个 塞尔通知 例程。 如果是, 塞尔通知 内核服务会唤醒设备 A 的所有正在等待发生的事件的进程。

此场景中的变体涉及级联链,其中只有某些设备驱动程序已注册 通知 例程。 在此情况下,每个级别的 塞尔通知 内核服务都将调用以上级别的 通知 例程,直到迂到未注册任何 通知 例程的级别为止。 此时,对于级联链的头部的设备驱动程序,所有感兴趣的事件都将确定为 true。 如果在高于当前级别的级别中注册了任何 通知 例程,那么从不调用这些例程。

从 fp_select 内核服务返回

fp_select 内核服务不会等待任何所选事件变为 true ,但会在对对象的 ddselect 例程的调用完成后立即返回。

如果成功调用了对象的选择例程,那么 fp_select 内核服务的返回码将设置为对象的 ddselect 例程所提供的返回码。

执行环境

仅可从 流程环境 调用 fp_select 内核服务。

返回值

描述
重大安全事件数量 指示成功完成。
EAGAIN 指示内部数据结构的分配已失败。 尔特内文特普 参数不会更新。
EINVAL 表明 菲普 参数不是有效的文件指针。 尔特内文特普 参数已设置了 POLLNVAL 标志。

还可以将 fp_select 内核服务设置为指定对象的 ddselect 例程中的非零返回码。 尔特内文特普 参数已设置了 POLLERR 标志。