檢視原始碼 儀器功能

每個物件的使用者定義儀器功能會將受管理的物件連接到實際資源。 此函式會在 getset 操作時由代理程式呼叫。此函式可以讀取一些硬體暫存器、執行計算,或執行任何實作與概念變數相關聯的語意所需的操作。這些函式必須針對純量變數和表格編寫。它們會在關聯檔案中指定,關聯檔案是一個文字檔。在此檔案中,每個受管理物件的 OBJECT IDENTIFIER 或符號名稱會與 Erlang 元組 {Module,``Function, ListOfExtraArguments} 相關聯。

當在 SNMP 操作中參照受管理物件時,會呼叫相關聯的 {Module, Function, ListOfExtraArguments}。此函式會套用至一些標準引數(例如,操作類型)和使用者提供的額外引數。

儀器功能必須針對純量變數和表格的 getset 編寫,且僅針對表格的 get-next 編寫。get-bulk 操作會轉換為一系列對 get-next 的呼叫。

儀器功能

以下章節說明應如何在 Erlang 中針對不同的操作定義儀器功能。在以下內容中,RowIndex 是表格的索引鍵值清單,而 Column 是一個欄號。

這些函式會在 儀器功能定義中詳細說明。

新增/刪除操作

對於純量變數

variable_access(new [, ExtraArg1, ...])
variable_access(delete [, ExtraArg1, ...])

對於表格

table_access(new [, ExtraArg1, ...])
table_access(delete [, ExtraArg1, ...])

當 MIB 分別卸載或載入時,會針對 MIB 中的每個物件呼叫這些函式。

Get 操作

對於純量變數

variable_access(get [, ExtraArg1, ...])

對於表格

table_access(get,RowIndex,Cols [,ExtraArg1, ...])

ColsColumn 的清單。代理程式會排序傳入的變數,以便同時提供對同一列(相同索引)的所有操作。這樣做的原因是資料庫通常會逐列擷取資訊。

這些函式必須傳回關聯變數的目前值。

Set 操作

對於純量變數

variable_access(set, NewValue [, ExtraArg1, ...])

對於表格

table_access(set, RowIndex, Cols [, ExtraArg1,..])

Cols 是元組 {Column, NewValue} 的清單。

如果指派成功,這些函式會傳回 noError,否則會傳回錯誤碼。

Is-set-ok 操作

作為 set 操作的補充,可以指定一個測試函式。此函式具有與上述 set 操作相同的語法,不同之處在於第一個引數是 is_set_ok 而不是 set。此函式會在設定變數之前呼叫。其目的是確保允許將變數設定為新值。

variable_access(is_set_ok, NewValue [, ExtraArg1, ...])

對於表格

table_access(set, RowIndex, Cols [, ExtraArg1,..])

Cols 是元組 {Column, NewValue} 的清單。

Undo 操作

已使用 is_set_ok 呼叫的函式會再次呼叫,如果沒有錯誤,則使用 set,如果發生錯誤,則使用 undo。透過這種方式,可以在 is_set_ok 操作中保留資源,在 undo 操作中釋放資源,或在 set 操作中將資源永久化。

variable_access(undo, NewValue [, ExtraArg1, ...])

對於表格

table_access(set, RowIndex, Cols [, ExtraArg1,..])

Cols 是元組 {Column, NewValue} 的清單。

GetNext 操作

GetNext 操作應僅針對表格定義,因為代理程式可以在 MIB 中找到純變數的下一個實例,並使用 get 操作呼叫儀器。

table_access(get_next, RowIndex, Cols [, ExtraArg1, ...])

Cols 是大於或等於零的整數清單。這表示儀器應尋找下一個可存取的實例。此函式會傳回元組 {NextOid, NextValue}endOfTableNextOid 應是表格中受管理物件的詞彙下一個可存取實例。它應是一個整數清單,其中第一個整數是欄,清單的其餘部分是下一列的索引。如果傳回 endOfTable,代理程式會繼續在其他變數和表格中搜尋下一個實例。

RowIndex 可以是空清單、未完全指定的列索引或未指定列的索引。

此操作最好用範例來說明。

GetNext 範例

名為 myTable 的表格有五個欄。前兩個是索引鍵(無法存取),表格有三列。此表格的儀器功能稱為 my_table

Contents of my_table

注意

不適用表示無法存取。

管理員發出以下 getNext 要求

getNext{ myTable.myTableEntry.3.1.1,
         myTable.myTableEntry.5.1.1 }

由於這兩個操作都涉及 1.1 索引,因此會轉換為一次對 my_table 的呼叫

my_table(get_next, [1, 1], [3, 5])

在此呼叫中,[1, 1]RowIndex,其中索引鍵 1 的值為 1,而索引鍵 2 的值為 1,[3, 5] 是要求的欄清單。此函式現在應傳回詞彙下一個元素

[{[3, 1, 2], d}, {[5, 1, 2], f}]

這會在下表中說明

GetNext from [3,1,1] and [5,1,1].

管理員現在發出以下 getNext 要求

getNext{ myTable.myTableEntry.3.2.1,
         myTable.myTableEntry.5.2.1 }

這會轉換為一次對 my_table 的呼叫

my_table(get_next, [2, 1], [3, 5])

此函式現在應傳回

[{[4, 1, 1], b}, endOfTable]

這會在下表中說明

GetNext from [3,2,1] and [5,2,1].

管理員現在發出以下 getNext 要求

getNext{ myTable.myTableEntry.3.1.2,
         myTable.myTableEntry.4.1.2 }

這會轉換為一次對 my_table 的呼叫

my_table(get_next, [1, 2], [3, 4])

此函式現在應傳回

[{[3, 2, 1], g}, {[5, 1, 1], c}]

這會在下表中說明

GetNext from [3,1,2] and [4,1,2].

管理員現在發出以下 getNext 要求

getNext{ myTable.myTableEntry,
         myTable.myTableEntry.1.3.2 }

這會轉換為兩次對 my_table 的呼叫

my_table(get_next, [], [0]) and
my_table(get_next, [3, 2], [1])

此函式現在應傳回

[{[3, 1, 1], a}] and
[{[3, 1, 1], a}]

在這兩種情況下,都應傳回表格中的第一個可存取元素。由於索引鍵欄無法存取,這表示第三欄是第一列。

注意

通常,上述函式的行為與顯示的完全相同,但它們可以自由執行其他操作。例如,get 請求可能會產生副作用,例如設定其他變數,或許是全域 lastAccessed 變數。

使用額外引數

ListOfExtraArguments 可用來編寫泛型函式。此清單會附加到每個函式的標準引數。考量裝置的兩個唯讀變數,物件識別碼分別為 1.1.23.4 和 1.1.7 的 ipAdrname。若要存取這些變數,可以實作 MIB 中的兩個 Erlang 函式 ip_accessname_access。可以在文字檔中指定這些函式,如下所示

{ipAdr, {my_module, ip_access, []}}.
% Or using the oid syntax for 'name'
{[1,1,7], {my_module, name_access, []}}.

ExtraArgument 參數是空清單。例如,當代理程式收到對 ipAdr 變數的 get 請求時,會呼叫 ip_access(get)。此函式傳回的值是 get 請求的答案。

如果 ip_accessname_access 的實作方式類似,我們可以使用 ListOfExtraArguments 編寫 generic_access 函式

{ipAdr, {my_module, generic_access, ['IPADR']}}.
% The mnemonic 'name' is more convenient than 1.1.7
{name, {my_module, generic_access, ['NAME']}}.

當代理程式收到與上述相同的 get 請求時,會呼叫 generic_access(get,'IPADR')

另一個更接近硬體的可能性是

{ipAdr, {my_module, generic_access, [16#2543]}}.
{name, {my_module, generic_access, [16#A2B3]}}.

預設儀器

當 MIB 定義工作完成時,還剩下兩個主要問題。

  • 實作 MIB
  • 實作管理員應用程式。

實作 MIB 可能是一項繁瑣的工作。最有可能的是,需要在實作所有表格和變數之前測試代理程式。在這種情況下,預設儀器功能非常有用。此工具組可以針對變數以及表格產生預設儀器功能。因此,會在沒有任何程式設計的情況下產生可處理 setgetget-next 和表格操作的執行原型代理程式。

代理程式會將值儲存在基於標準模組 ets 的內部揮發性資料庫中。但是,可以讓 MIB 編譯器產生使用內部永久性資料庫或 Mnesia DBMS 的函式。如需更多資訊,請參閱 Mnesia 使用者指南和參考手冊的 SNMP 章節,模組 snmp_generic

當實作 MIB 的部分時,您會重新編譯它並繼續使用預設函式。透過這種方法,可以逐步開發 SNMP 代理程式。

預設儀器可讓管理員端的應用程式與代理程式同時開發和測試。ASN.1 檔案完成後,立即讓 MIB 編譯器產生預設實作,並從此開發管理應用程式。

表格操作

針對使用 SNMPv2 中的 RowStatus 文字慣例(在 STANDARD-MIB 和 SNMPv2-TC 中定義)的表格,產生表格的預設函式可以運作。

注意

我們強烈建議針對每個可以從管理員修改的表格使用 RowStatus 慣例,即使是新設計的 SNMPv1 MIB 也是如此。在 SNMPv1 中,每個人都發明了自己的方案來模擬表格操作,這導致了許多不一致之處。SNMPv2 中的慣例既靈活又強大,並且已成功測試。如果表格是唯讀的,則不應使用 RowStatus 欄。

原子 Set

在 SNMP 中,set 操作是原子的。在 set 操作中指定的所有變數都會變更,否則都不會變更。因此,set 操作分為兩個階段。在第一階段,會根據 MIB 中變數的定義來檢查每個變數的新值。會檢查以下定義

  • 類型
  • 長度
  • 範圍
  • 變數是可寫入的,並且在 MIB 檢視中。

在第一階段結束時,會針對每個純量變數和每組表格操作呼叫使用者定義的 is_set_ok 函式。

如果沒有發生錯誤,則會執行第二階段。此階段會針對所有變數呼叫使用者定義的 set 函式。

如果在 is_set_ok 階段或 set 階段發生錯誤,則所有已使用 is_set_ok 呼叫但未使用 set 呼叫的函式,都會使用 undo 呼叫。

這個交易機制有一些限制。如果變數之間存在複雜的相依性,例如 monthday 之間,則需要另一種機制。透過更通用的交易機制,可以避免將日期設定為「2 月 31 日」。您可以繼續並找到越來越複雜的情況,並建構一個 N 階段的設定機制。此工具組僅包含一個簡單的機制。

交易機制最常見的應用是將列操作保持在一起。由於我們的代理程式會對列操作進行排序,因此實作的機制與 RowStatus(特別是 'createAndWait' 值)結合,可以優雅地解決大多數問題。