Linux 用于读取 z/VM 监视器记录的 API¶
日期 : 2004-Nov-26
作者:Gerald Schaefer (geraldsc@de.ibm.com)
描述¶
本项工作提供了一个新的 Linux API,其形式为一个杂项字符设备(misc char device),可从用户空间使用,并允许读取由 z/VM 的 *MONITOR 系统服务收集的 z/VM 监视器记录。
用户需求¶
要访问此 API 的 z/VM 客户机需要进行配置,以允许到 *MONITOR 服务的 IUCV 连接,即在其用户条目中需要包含 IUCV *MONITOR 语句。如果要使用的监视器 DCSS 是受限制的(可能性很大),您还需要 NAMESAVE <DCSS NAME> 语句。本项目将使用 IUCV 设备驱动程序来访问 z/VM 服务,因此您需要一个支持 IUCV 的内核。您还需要的 z/VM 版本为 4.4 或 5.1。
加载监视器 DCSS 有两种可选方案(示例假设监视器 DCSS 从 144 MB 开始,到 152 MB 结束)。您可以使用 Class E 特权 CP 命令 Q NSS MAP 来查询监视器 DCSS 的位置(值 BEGPAG 和 ENDPAG 的单位为 4K 页)。
有关 DEF STOR 和 Q NSS MAP 命令的更多信息,请参见《CP 命令和实用程序参考》(CP Command and Utility Reference, SC24-6081-00);有关 DCSS 的更多信息,请参见《保存段规划与管理》(Saved Segments Planning and Administration, SC24-6116-00)。
第一种方案:¶
您可以使用 CP 命令 DEF STOR CONFIG 在客户机虚拟存储器中围绕 DCSS 的地址范围定义一个“内存洞”(memory hole)。
示例:DEF STOR CONFIG 0.140M 200M.200M
这定义了两个存储块,第一个大小为 140MB,从地址 0MB 开始;第二个大小为 200MB,从地址 200MB 开始,总存储空间为 340MB。请注意,第一个块应始终从 0 开始,且大小至少为 64MB。
第二种方案:¶
您的客户机虚拟存储器必须在 DCSS 的起始地址之前结束,并且您必须在 parmfile 中指定 “mem=” 内核参数,其值大于 DCSS 的结束地址。
示例
DEF STOR 140M
这为您的客户机定义了 140MB 的存储大小,并在 parmfile 中添加了参数 “mem=160M”。
用户接口¶
该字符设备实现为一个名为 “monreader” 的内核模块,可以通过 modprobe 命令加载,或者也可以将其编译到内核中。有一个可选的模块(或内核)参数 “mondcss”,用于指定监视器 DCSS 的名称。如果模块被编译到内核中,则可以在 parmfile 中指定内核参数 “monreader.mondcss=<DCSS NAME>”。
如果未指定,DCSS 的默认名称为 “MONDCSS”。如果已有其他用户连接到 *MONITOR 服务(例如性能工具包 Performance Toolkit),则监视器 DCSS 已经定义,您必须使用相同的 DCSS。CP 命令 Q MONITOR(Class E 特权)会显示监视器 DCSS 的名称(如果已定义)以及连接到 *MONITOR 服务的用户。如果您的 z/VM 还没有监视器 DCSS,请参考《z/VM 性能》(z/VM Performance, SC24-6109-00) 一书了解如何创建它。您需要 Class E 特权来定义和保存 DCSS。
示例:¶
modprobe monreader mondcss=MYDCSS
这会加载模块并将 DCSS 名称设置为 “MYDCSS”。
注意:¶
此 API 不提供控制 *MONITOR 服务的接口(例如指定应收集哪些数据)。这可以通过 CP 命令 MONITOR(Class E 特权)来完成,参见《CP 命令和实用程序参考》。
使用 udev 的设备节点:¶
加载模块后,将创建一个字符设备以及设备节点 /<udev 目录>/monreader。
不使用 udev 的设备节点:¶
如果您的发行版不支持 udev,则不会自动创建设备节点,您必须在加载模块后手动创建它。因此,您需要知道设备的主设备号和次设备号。这些编号可以在 /sys/class/misc/monreader/dev 中找到。
输入 cat /sys/class/misc/monreader/dev 将输出形如 <major>:<minor> 的格式。可以通过 mknod 命令创建设备节点,输入 mknod <name> c <major> <minor>,其中 <name> 是要创建的设备节点的名称。
示例:¶
# modprobe monreader
# cat /sys/class/misc/monreader/dev
10:63
# mknod /dev/monreader c 10 63
这会使用默认的监视器 DCSS (MONDCSS) 加载模块并创建一个设备节点。
文件操作:¶
支持以下文件操作:open、release、read、poll。有两种可选的读取方法:结合轮询的非阻塞读取,或者不使用轮询的阻塞读取。不支持 IOCTL。
读取 (Read):¶
从设备读取提供了一个 12 字节的监视器控制元素 (MCE),后跟一组或多组连续的监视器记录(类似于没有 4K 控制块的 CMS 实用程序 MONWRITE 的输出)。MCE 包含有关后续记录集类型(采样/事件数据)、其中包含的监视器域以及记录集在监视器 DCSS 中的起始和结束地址的信息。起始和结束地址可用于确定记录集的大小,结束地址是最后一个数据字节的地址。需要起始地址才能正确处理“帧尾”(end-of-frame)记录(域 1,记录 13),即它可用于确定相对于 4K 页(帧)边界的记录起始偏移量。
有关监视器控制元素布局的描述,请参见《z/VM 性能》文档中的“附录 A:*MONITOR”。监视器记录的布局可以在此处找到 (z/VM 5.1):https://www.vm.ibm.com/pubs/mon510/index.html
monreader 设备提供的数据流布局如下
...
<0 byte read>
<first MCE> \
<first set of records> |
... |- data set
<last MCE> |
<last set of records> /
<0 byte read>
...
一个数据集中可能存在多个 MCE 与相应记录集的组合,每个数据集的结束由返回值为 0(读取 0 字节)的成功读取操作指示。在成功读取完整的数据集(包括最后的 0 字节读取)之前,任何接收到的数据都必须被视为无效。因此,在处理数据之前,您应该始终将完整的数据集读取到缓冲区中。
数据集的最大大小可以与监视器 DCSS 的大小一样大,因此请适当地设计缓冲区大小或使用动态内存分配。加载模块后,监视器 DCSS 的大小将打印到 syslog 中。您还可以使用(Class E 特权)CP 命令 Q NSS MAP 列出所有可用的段及其相关信息。
与大多数字符设备一样,错误条件通过返回负值作为读取的字节数来表示。在这种情况下,errno 变量指示错误条件:
- EIO
回复失败,读取的数据无效,应用程序应丢弃自上次大小为 0 的成功读取以来所读取的数据。
- EFAULT
copy_to_user 失败,读取的数据无效,应用程序应丢弃自上次大小为 0 的成功读取以来所读取的数据。
- EAGAIN
如果当前没有可用数据,则在非阻塞读取时发生。没有数据丢失或损坏,只需重试,或者对非阻塞读取使用轮询。
- EOVERFLOW
达到消息限制,自上次大小为 0 的成功读取以来读取的数据是有效的,但后续记录可能会丢失。
在最后一种情况下 (EOVERFLOW) 可能会丢失数据,在前两种情况下 (EIO, EFAULT) 则一定会丢失数据。应用程序是继续读取后续数据还是退出,由应用程序自行决定。
打开 (Open):¶
只允许一个用户打开该字符设备。如果它已经在使用中,open 函数将失败(返回负值)并设置 errno 为 EBUSY。如果无法建立到 *MONITOR 服务的 IUCV 连接,open 函数也可能会失败。在这种情况下,errno 将被设置为 EIO,并且带有 IPUSER SEVER 代码的错误消息将被打印到 syslog 中。IPUSER SEVER 代码在《z/VM Performance》一书的附录 A 中有描述。
注意:¶
一旦打开设备,就会接受传入的消息,并且这些消息将计入消息限制中,即:在不读取设备的情况下打开设备最终会引发“达到消息限制”错误(EOVERFLOW 错误代码)。