表 27–2 中列出了 io 探测器的参数类型。表 27–1 中介绍了这些参数。
表 27–2 io 探测器参数
探测器 |
args[0] |
args[1] |
args[2] |
---|---|---|---|
start |
struct buf * |
devinfo_t * |
fileinfo_t * |
done |
struct buf * |
devinfo_t * |
fileinfo_t * |
wait-start |
struct buf * |
devinfo_t * |
fileinfo_t * |
wait-done |
struct buf * |
devinfo_t * |
fileinfo_t * |
每个 io 探测器的参数由指向 buf(9S) 结构的指针、指向 devinfo_t 的指针和指向 fileinfo_t 的指针组成。本节将详细介绍这些结构。
bufinfo_t 结构简要介绍了 I/O 请求。start、done、wait-start 和 wait-done 探测器中的 args[0] 指向对应于 I/O 请求的缓冲区。bufinfo_t 结构定义如下所示:
typedef struct bufinfo { int b_flags; /* flags */ size_t b_bcount; /* number of bytes */ caddr_t b_addr; /* buffer address */ uint64_t b_blkno; /* expanded block # on device */ uint64_t b_lblkno; /* block # on device */ size_t b_resid; /* # of bytes not transferred */ size_t b_bufsize; /* size of allocated buffer */ caddr_t b_iodone; /* I/O completion routine */ dev_t b_edev; /* extended device */ } bufinfo_t;
b_flags 成员指示 I/O 缓冲区的状态,它由不同状态值的按位或的结果组成。表 27–3 中介绍了有效的状态值。
表 27–3 b_flags 值
B_DONE |
指示数据传送已完成。 |
B_ERROR |
指示 I/O 传送错误。它与 b_error 字段一起设置。 |
B_PAGEIO |
指示分页的 I/O 请求中正在使用该缓冲区。有关更多信息,请参见 b_addr 字段的说明。 |
B_PHYS |
指示正在对指向用户数据区的物理(直接)I/O 使用该缓冲区。 |
B_READ |
指示将从外围设备中读取数据到主内存中。 |
B_WRITE |
指示将数据从主内存传送到外围设备。 |
B_ASYNC |
I/O 请求为异步请求,不会被等待。wait-start 和 wait-done 探测器不会对异步 I/O 请求触发。请注意,定向为异步的某些 I/O 可能不会设置 B_ASYNC:异步 I/O 子系统可能通过使单独的工作线程执行同步 I/O 操作来实现异步请求。 |
b_bcount 字段表示要作为 I/O 请求一部分进行传送的字节数。
除非设置了 B_PAGEIO,否则 b_addr 字段表示 I/O 请求的虚拟地址。除非设置了 B_PHYS(此情况下该地址为用户虚拟地址),否则该地址为内核虚拟地址。如果设置了 B_PAGEIO,则 b_addr 字段将包含内核专用数据。仅能设置 B_PHYS 和 B_PAGEIO 的其中之一,否则将不会设置任何标志。
b_lblkno 字段标识设备上要访问的逻辑块。逻辑块到物理块(如柱面、磁轨等)的映射由设备定义。
b_resid 字段设置为由于发生错误而未传送的字节数。
b_bufsize 字段包含分配的缓冲区大小。
b_iodone 字段标识 I/O 完成时内核中调用的特定例程。
b_error 字段可能包含发生 I/O 错误时从驱动程序返回的错误代码。b_error 将与在 b_flags 成员中设置的 B_ERROR 位一起设置。
b_edev 字段包含所访问设备的主要和次要设备编号。使用者可使用 D 子例程 getmajor() 和 getminor() 从 b_edev 字段中提取主要和次要设备编号。
devinfo_t 结构提供有关设备的信息。start、done、wait-start 和 wait-done 探测器中的 args[1] 指向对应于 I/O 的目标设备的 devinfo_t 结构。devinfo_t 的成员如下所示:
typedef struct devinfo { int dev_major; /* major number */ int dev_minor; /* minor number */ int dev_instance; /* instance number */ string dev_name; /* name of device */ string dev_statname; /* name of device + instance/minor */ string dev_pathname; /* pathname of device */ } devinfo_t;
dev_major 字段是设备的主要编号。有关更多信息,请参见 getmajor(9F)。
dev_minor 字段是设备的次要编号。有关更多信息,请参见 getminor(9F)。
dev_instance 字段是设备的实例编号。设备实例不同于次要编号。次要编号是由设备驱动程序管理的抽象对象。实例编号是设备节点的一个属性。可使用 prtconf(1M) 来显示设备节点实例编号。
dev_name 字段是用于管理设备的设备驱动程序的名称。可使用 prtconf(1M) 的 -D 选项显示设备驱动程序名称。
dev_statname 字段是 iostat(1M) 报告的设备名称。此名称同时对应于 kstat(1M) 报告的内核统计信息的名称。提供此字段是为了便于快速地将异常的 iostat 或 kstat 输出与实际 I/O 活动相关联。
dev_pathname 字段是设备的完整路径。此路径可指定为 prtconf(1M) 的参数,以获取详细的设备信息。dev_pathname 指定的路径包括用于表示设备节点、实例编号和次要节点的组件。但是,不必在统计信息名称中表示所有这三个元素。对于某些设备,统计信息名称由设备名称和实例编号组成。对于其他设备,统计信息名称则由设备名称和次要节点编号组成。因此,具有相同 dev_statname 的两个设备的 dev_pathname 可能会不同。
fileinfo_t 结构提供有关文件的信息。start、done、wait-start 和 wait-done 探测器中的 args[2] 指向 I/O 所对应的文件。在分发 I/O 请求时,文件信息存在与否将取决于提供此信息的文件系统。某些文件系统(尤其是第三方文件系统)可能不会提供此信息。I/O 请求也可能是从不包含任何文件信息的文件系统发出的。例如,对文件系统元数据的任何 I/O 请求,将不会与任何一个文件关联。最后,一些高度优化的文件系统可能将不相交文件中的 I/O 聚集为单个 I/O 请求。在此情况下,文件系统可能会为表示大多数 I/O 的文件或表示部分 I/O 的文件提供文件信息。或者,在此情况下文件系统可能根本不提供任何文件信息。
fileinfo_t 结构的定义如下所示:
typedef struct fileinfo { string fi_name; /* name (basename of fi_pathname) */ string fi_dirname; /* directory (dirname of fi_pathname) */ string fi_pathname; /* full pathname */ offset_t fi_offset; /* offset within file */ string fi_fs; /* filesystem */ string fi_mount; /* mount point of file system */ } fileinfo_t;
fi_name 字段包含文件的名称,但不包括任何目录部分。如果没有任何文件信息与 I/O 关联,则 fi_name 字段将设置为字符串 <none>。在极少数情况下,与文件关联的路径名可能未知。在此情况下,fi_name 字段将设置为字符串 <unknown>。
fi_dirname 字段仅包含文件名的目录部分。与 fi_name 一样,如果不存在任何文件信息,此字符串可能会设置为 <none>;如果与该文件关联的路径名未知,此字符串可能会设置为 <unknown>。
fi_pathname 字段包含文件的完整路径名。与 fi_name 一样,如果不存在任何文件信息,此字符串可能会设置为 <none>;如果与该文件关联的路径名未知,此字符串可能会设置为 <unknown>。
fi_offset 字段包含文件中的偏移,如果文件信息不存在或者文件系统未指定偏移,则此字段将为 1。