查看源代码 MIB 编译器
MIB 编译器 章节描述了 MIB 编译器,包含以下主题
- 操作
- 导入
- MIB 之间的一致性检查
- .hrl 文件生成
- Emacs 集成
- 与标准的偏差
注意
导入 MIB 时,请确保导入的 MIB 以及正在导入的 MIB 使用相同版本的 SNMP 编译器进行编译。
操作
在编译之前,必须使用 ASN.1 表示法将 MIB 编写为 SMIv1 或 SMIv2 文本文件。此文本文件必须与 MIB 同名,但后缀为 .mib
。这对于处理 IMPORT
语句是必要的。
关联文件包含 MIB 的检测功能的名称,应具有后缀 .funcs
。如果编译器找不到关联文件,则会给出警告消息并使用默认的检测功能。(有关更多详细信息,请参阅 默认检测)。
MIB 编译器通过调用 snmpc:compile(<mibname>).
启动。例如
snmpc:compile("RFC1213-MIB").
输出是一个名为 <mibname>.bin
的新文件。
MIB 编译器可以理解 SMIv1 和 SMIv2 MIB。它使用 MODULE-IDENTITY 语句来确定 MIB 是使用 SMI 版本 1 还是 2 编写的。
导入 MIB
编译器处理 IMPORT
语句。重要的是导入已编译的文件,而不是 ASN.1(源)文件。必须重新编译 MIB,才能使更改对导入它的其他 MIB 可见。
导入的 MIB 的编译文件必须存在于当前目录或当前路径中的目录中。路径使用 {i, Path}
选项提供,例如
snmpc:compile("MY-MIB",
[{i, ["friend_mibs/", "../standard_mibs/"]}]).
也可以使用 il
选项以类似于 "include_lib"
的方式从 OTP 应用程序导入 MIB。例如
snmpc:compile("MY-MIB",
[{il, ["snmp/priv/mibs/", "myapp/priv/mibs/"]}]).
在 OTP 系统中查找 snmp
和 myapp
应用程序的最新版本,并将扩展后的路径用作包含路径。
请注意,SMIv2 MIB 可以导入 SMIv1 MIB,反之亦然。
以下 MIB 是 Erlang SNMP 编译器的内置 MIB:SNMPv2-SMI、RFC-1215、RFC-1212、SNMPv2-TC、SNMPv2-CONF 和 RFC1155-SMI。因此,它们不能单独编译。
MIB 一致性检查
编译 MIB 时,编译器会检测是否有多个被管理对象使用相同的 OBJECT IDENTIFIER
。如果是这种情况,它会发出错误消息。但是,编译器无法检测不同 MIB 之间的 Oid 冲突。这些类型的冲突会在加载时生成错误。为了避免这种情况,可以使用以下函数在 MIB 之间进行一致性检查
erl>snmpc:is_consistent(ListOfMibNames).
ListOfMibNames
是已编译的 MIB 的列表,例如 ["RFC1213-MIB", "MY-MIB"]
。该函数还执行陷阱定义的一致性检查。
.hrl 文件生成
可以从已编译的 MIB 文件生成包含 Erlang 常量定义的 .hrl
文件。然后可以将此文件包含在 Erlang 源代码中。该文件将包含以下常量:
- 表、表项和变量的对象标识符
- 列号
- 枚举值
- 变量和表列的默认值。
使用以下命令从 MIB 生成 .hrl 文件
erl>snmpc:mib_to_hrl(MibName).
Emacs 集成
使用 Emacs 编辑器,next-error
(C-X `
) 函数可用于指示发生编译错误的位置,前提是错误消息由行号描述。
使用 M-x compile
从 Emacs 内部编译 MIB,然后输入
erl -s snmpc compile <MibName> -noshell
<MibName>
的示例是 RFC1213-MIB
。
从 Shell 或 Makefile 编译
可以使用 erlc
命令来编译 SNMP MIB。例如
erlc MY-MIB.mib
支持所有标准的 erlc
标志,例如
erlc -I mymibs -o mymibs -W MY-MIB.mib
可以使用 +
语法指定 MIB 编译器特有的标志
erlc +'{group_check,false}' MY-MIB.mib
与标准的偏差
在某些方面,Erlang MIB 编译器并未完全遵循或实现 SMI。以下是差异
- 必须按以下顺序编写表:
tableObject
、entryObject
、column1
、...、columnN
(按顺序)。 - 整数值,例如在
SIZE
表达式中,必须以十进制语法输入,而不是以十六进制或位语法输入。 - 符号名称在 MIB 内和系统内必须是唯一的。
- SMIv2 中允许使用连字符(一种务实的方法)。这样做的原因是,根据 SMIv2,连字符允许用于从 SMIv1 转换的对象,但不允许用于其他对象。这对于编译器来说是无法检查的。
- 如果一个单词是 SMIv1 或 SMIv2 中的任何一个关键字,则它也是编译器中的关键字(仅与 SMIv1 不同)。
- 表中的索引必须是对象,而不是类型(仅与 SMIv1 不同)。
- 实现了对类型的语义检查的一个子集。例如,严格来说,
TimeTicks
不能被子类化,但编译器允许这样做(标准 MIB 必须通过编译器)(仅与 SMIv2 不同)。 - 未实现
MIB.Object
语法(因为所有对象都必须是唯一的)。 - 两个不同的名称不能定义相同的 OBJECT IDENTIFIER。
- SEQUENCE 构造中的类型检查是非严格的(即,可以指定子类型)。这样做的原因是,一些标准 MIB 使用了这种方法。
- 定义通常具有状态字段。当状态字段的值为 deprecated 时,MIB 编译器将忽略此定义。使用 MIB 编译器选项
{deprecated,true}
,MIB 编译器不会忽略已弃用的定义。 - 对象具有 DESCRIPTIONS 字段。默认情况下,描述字段不会包含在已编译的 mib 中。为了获取描述,必须使用选项
description
编译 mib。