uphysio 或 uphysio_fast 内核服务

用途

使用 乌约 结构对块设备执行字符 I/O。

语法

#include <sys/types.h>
#include <sys/errno.h>
#include <sys/buf.h>
#include <sys/uio.h>
int uphysio (uiop, rw, buf_cnt, devno, strat, mincnt, minparms)
struct uio * uiop;
int  rw;
uint  buf_cnt;
dev_t  devno;
int (* strat)( );
int (* mincnt )( );
void * minparms;

int uphysio_fast(uiop, rw, buf_cnt, devno, strat, max_xfer, options, blk_align)
struct uio *uiop;
int rw;
uint buf_cnt;
dev_t devno;
int (* strat)( );
uint64_t max_xfer;
uint32_t options;
uint32_t blk_align;

参数

下表包含用于 乌普希西奥uphysio_fast的参数:

描述
乌约普 指向用于描述要使用字符到块 I/O 进行传输的数据缓冲区的 乌约 结构
rw 指示读操作或写操作。 该标志的值为 读取 (_READ) 表示读操作。 此标志的值为 写 (_WRITE) 表示写操作。
布夫克恩特 指定在调用由 斯特拉特 参数指定的策略例程时要使用的最大 布夫 结构 数。 此参数用于指示设备可以支持的最大并行量,并使 I/O 重新驱动时间最小化。 布夫克恩特 参数的值可以在 1 到 64 范围内。
德夫诺 指定 主要和次要设备号。 对于 乌普希西奥 服务,此参数指定在调用由 斯特拉特 参数指定的策略例程之前要放置在 布夫 结构中的设备号。
斯特拉特 表示指向该设备的 ddstrategy 例程的函数指针。
明恩特 表示一个例程的函数指针,该例程用于在启动策略例程之前,根据设备的要求,减小 布夫 结构中指定的数据传输大小。 在将此信息传递到策略例程之前,还可以使用此例程来更新 布夫 结构中的扩展参数信息。
明帕姆斯 指向要由 明恩特 参数使用的参数。
Max_xfer 指定设备的最大传输大小 (以字节为单位)。
选项 指定要存储在缓冲区头的 b_options 字段中的值。
Blk_align 可选参数,用于对发送到指定 I/O 策略例程的所有传输强制执行最小块对齐。 此值以字节为单位指定。 如果指定了非零值,那么将检查每个 I/O 向量以确保它是此值的倍数。 如果不在对齐边界上,那么传输请求将失败。 在指定块对齐时,假定由 Max_xfer 参数指定的最大传输大小是块对齐的。

描述

乌普希西奥uphysio_fast 内核服务会对块设备执行字符 I/O。 乌普希西奥uphysio_fast 服务尝试将由 布夫克恩特 参数指定的 布夫 头数发送至指定的策略例程。 这些 布夫 结构 是使用 乌约普 参数指定的 乌约 结构 中的数据构造的。

乌普希西奥uphysio_fast 服务最初从每个服务传输数据区描述iovec在各个 布夫 头中找到 乌约 结构中的元素。 这些头稍后将发送到策略例程。 乌普希西奥uphysio_fast 内核服务尝试处理的数据区数与 布夫 头数允许的数据区数相同。 然后,它将使用 布夫 头列表来调用策略例程。

uphysio_fast 服务使用指定的最大传输大小来定制数据传输长度,并避免使用 乌普希西奥 服务需要的 明恩特 例程时迂到上下文切换开销。 在调用者已知道最大传输大小且不需要更新缓冲区头字段的环境中,应该使用此服务来减少 I/O 路径长度。

准备单个 buf 头

明恩特 参数指定的例程将在 布夫 头之前进行调用,该头是根据iovec元素,将添加到要发送到策略例程的 布夫 头的列表中。 明恩特 参数将与 明帕姆斯 指针一起传递到 布夫 头的指针。 此安排允许 明恩特 参数根据执行 I/O 操作的设备的要求来定制 布夫 头所描述的数据传输长度。 明恩特 参数还可以选择在 布夫 头中修改某些依赖于设备的字段。

明恩特 参数返回且没有任何错误时,会尝试将 布夫 头描述的数据缓冲区置顶。 如果由于内存不足而导致锁定操作失败,那么 布夫 头所描述的数据区将减少一半。 在尝试将缩小的数据区置顶之前, 布夫 头再次传递到 明恩特 参数以进行修改。

在出现以下三种情况之一之前,将重复此过程以缩小 布夫 头指定的传输:

  • 锁定操作成功。
  • 明恩特 参数指示一个错误。
  • 数据区大小将减小为 0。

当内存不足指示 pin 操作失败时,用于该操作的剩余部分的 布夫 头数将减少为 1。 这是因为在这些条件下尝试同时锁定多个数据区是不可取的。

如果用户尚未获取交叉内存描述符,那么需要进行进一步处理。 ( uio_segflg乌约 结构中的 字段指示用户是否已经初始化了跨内存描述符。 usr/include/sys/uio.h 文件包含有关此标志的可能值的信息。)

布夫 头描述的数据区成功置顶后, 乌普希西奥uphysio_fast 服务会验证用户对该数据区的访问权限。 它还获取跨内存描述符,以允许设备驱动程序中断处理程序限制对数据区的访问。

调用 "策略例程"

乌普希西奥uphysio_fast 内核服务获取跨内存描述符以允许设备驱动程序中断处理程序对数据区进行有限访问之后, 布夫 头将放入 布夫 头的列表中,以发送到 斯特拉特 参数指定的策略例程。

在以下情况下,将使用 布夫 头列表来调用 斯特拉特 参数指定的策略例程:

  • 该列表达到 布夫克恩特 参数指定的 布夫 个结构的数目。
  • 乌约 结构所描述的数据区已由 布夫 头完整描述。

列表中的 布夫 头是使用以下项链接在一起的: av_backav_forw在将 字段发送到策略例程之前。

正在等待 buf 头完成

当所有可用的 布夫 头都已发送到策略例程时, 乌普希西奥uphysio_fast 服务将等待一个或多个 布夫 头标记为完成。 IODONE 处理程序用于在等待来自策略例程的已完成的 布夫 头时唤醒 乌普希西奥uphysio_fast 服务。

乌普希西奥uphysio_fast 服务收到已完成的 布夫 头的通知时,将取消锁定关联的数据缓冲区并释放跨内存描述符。 (但是,仅当用户尚未获取交叉内存描述符时,才会释放该描述符。) 在以下条件下,在数据传输上检测到错误:

  • 已完成的 布夫 头具有非零值b_resid:NONE.
  • b_flags字段设置了 错误 (_ERROR) 标志。

乌普希西奥uphysio_fast 服务检测到错误时,不会将新的 布夫 头发送到策略例程。

乌普希西奥uphysio_fast 服务会等待已发送到策略例程的任何 布夫 头完成,然后向调用者返回错误代码。 如果未检测到任何错误,那么 布夫 头和任何其他已完成的 布夫 头将再次用于在策略例程变为可用时向其发送更多数据传输请求。 此过程将持续到 乌约 结构中描述的所有数据都已传输或者检测到错误为止。

在以下情况下, 乌普希西奥uphysio_fast 服务将返回到调用者:

  • 策略例程已将 所有 布夫 头标记为已完成。
  • 已传输由 乌约 结构指定的所有数据。

如果检测到错误,那么 乌普希西奥uphysio_fast 服务还会向调用者返回错误代码。

由 uphysio 或 uphysio_fast 内核服务检测到错误

当它检测到错误时, 乌普希西奥uphysio_fast 内核服务会报告检测到的最接近 乌约 结构所描述的数据区的开头的错误。 不会将其他 布夫 头发送到策略例程。 乌普希西奥uphysio_fast 内核服务等待发送到策略例程的所有 布夫 头都标记为完成。

但是,可能已在这两个事件之间向策略例程发送了其他 布夫 头:

  • 在策略例程检测到错误后。
  • 在通知 乌普希西奥uphysio_fast 服务已完成的 布夫 头中的错误情况之前。

发生错误时,返回的 乌约 结构中的各个字段可能反映也可能不反映错误。 该uio_iovuio_iovcnt字段未更新且包含其原始值。

uio_residuio_offset返回的 乌约 结构中的 字段指示策略例程根据所有字节的总和所传输的字节数 (b_bcount字段减去b_resid字段) 由策略例程处理的 布夫 头中的字段。 这些头包括 布夫 头,用于指示最接近原始 乌约 结构所描述的数据区开头的错误。 在检测到错误后完成的 布夫 头中的任何数据计数都不会反映在返回的 乌约 结构中。

执行环境

乌普希西奥uphysio_fast 内核服务只能从 流程环境 中进行调用。

返回值

描述
重大安全事件数量 指示成功完成。
ENOMEM 指示没有可用于必需的 布夫 头的内存。
EAGAIN 指示由于资源暂时不足的情况而导致操作失败。
EFAULT 指示以下情况:uio_segflg字段指示用户空间,并且用户没有访问缓冲区的权限。
EIO 或 buf 头中的 b_error 字段 指示策略例程所处理的 布夫 头中的 I/O 错误。
返回码来自 明恩特 参数 指示如果例程返回非零返回码,那么将返回来自 明恩特 参数的返回码。