繼續上文的講敘,在利用OpenIPMI現成的庫和例子程序以前,咱們須要理解OpenIPMI 代碼的結構和OpenIPMI程序運行的過程和特色。
OpenIPMI的目的就是要屏蔽IPMI協議的細節,給用戶提供快速實現SMS的框架和接口。所以,它內部替用戶已經實現了IPMI協議裏提到的各類類型(數據結構),好比sensor,sdr,sel,mc,sel,entity等等,同時使用面向對象的思想,提供了不少查詢和設置這些數據結構的方法。固然,爲了屏蔽不一樣平臺和接口的差異,OpenIPMI本身在用戶層封裝了一層timer機制、鎖同步機制。此外,爲了向用戶提供統一的操做方法,OpenIPMI自定義了一些額外的數據結構,好比domain,connection等等。結合文檔和原代碼的分析,咱們能夠看到OpenIPMI的數據結構比較多,相互關聯比較複雜:數據結構
經過上面的圖,咱們能夠看到最中間的ipmi_domain_t,它關聯了和BMC自己相關的mc,sdr,sensor,entity等數據結構,這些成員都是在這個域創建起來後須要初始化的。在上面圖最左上側的os_handler_s數據結構,就是對不一樣的內存管理、timer機制的封裝。而它下面的ipmi_con_s數據結構就是對BMC不一樣的接口好比KCS/Lan/IPMB的封裝,以向用戶提供統一的命令發送、鏈路創建的接口。和BMC自己相關的數據結構主要有ipmi_mc_s,它囊括了SEL/SDR/Sensor/Control信息以及處理OEM差別的函數,而SEL/SDR/Sensor/Control等信息數據又和相應的實體結構對應,每一個實體結構包括真實的物理信息,OpenIPMI爲此提供了許多設置和查詢的操做。以ipmi_sensor_s爲例子,它自己包括Lun/ Sensor number等基本信息,OpenIPMI又提供了對它的許多操做:
|| ipmi_sensor_convert_from_raw
|| stand_ipmi_sensor_convert_to_raw
|| stand_ipmi_sensor_get_tolerance
|| stand_ipmi_sensor_get_accuracy
|| stand_ipmi_sensor_reading_name_string
|| ipmi_sensor_get_callbacks
|| ipmi_sensor_set_callbacks
|| ipmi_sensor_set_event_enables
|| ipmi_sensor_enable_events
|| ipmi_sensor_disable_events
|| ipmi_sensor_rearm
|| ipmi_sensor_get_event_enables
|| ipmi_sensor_get_hysteresis
|| ipmi_sensor_set_hysteresis
|| ipmi_sensor_get_thresholds
|| ipmi_sensor_set_thresholds
|| ipmi_sensor_get_reading
|| ipmi_sensor_get_states
用戶只須要利用OpenIPMI提供的機制按照函數定義的格式正確調用就能快速高效構建本身的SMS。好比咱們須要每隔5秒鐘檢查系統上的全部sensor的讀值是否超出閾值,能夠利用OpenIPMI已經提供好的timer機制、回調機制和現成的函數接口實現便可。具體的過程以下:
1. 執行框架代碼:創建起來統一的os handler,初始化IPMI 庫,關聯connection和os handler, open一個domain,同時指定額外的初始化函數;
2. 初始化timer:OpenIPM提供的timer至關於定時觸發器,每隔一段時間和它關聯的進程就會執行一次。 具體而言,須要先初始化一個timeval和os_hnd_timer_id_t的數據結構,設置超時間隔,指定超時後執行的函數。這裏指定掃描系統全部sensor的函數做爲超時後執行的函數。而後經過os handler啓動定時器。這樣設置完成後,一旦定時器超時,指定的函數就會執行 。但須要注意的是,因爲定時器超時後不會再自動啓動,這個函數只會執行一次 。爲了讓指定的函數週期地按照固定的間隔執行,須要利用線程。
3.經過os handler調用creat_thread建立一個線程 ,在線程裏面執行OpenIPMI事件驅動模型的主要循環,這個循環裏面就包括重啓定時器。
4. 利用OpenIPMI的回調機制實現sensor掃描:首先在超時後執行的函數裏面調用枚舉sensor的函數:
ipmi_entity_iterate_sensors(myentity, iterate_sensor, NULL);
注意這個函數的第二個參數是須要用戶自定義的回調函數,它有固定的參數格式:
static iterate_sensor(ipmi_entity_t *ent, ipmi_sensor_t *sensor, void * b_data)
特別須要強調的是,並非ipmi_entity_interate_sensors()函數執行完了後,立刻就會執行到了iterate_sensor,從前者都後者在OpenIPMI內部又經歷了三四層的回調,而且當執行到後者時,它的前面兩個參數恰好指向當前遍歷的sensor的ipmi_entity_t 和 ipmi_sensor_t結構,這樣用戶根據須要直接訪問這倆參數就能夠了。至於底層如何從/dev/ipmi0設備經過IOCTL發送IPMI sensor reading請求並讀取響應值,OpenIPMI都已經處理好,用戶不須要再操心。相似的,若是用戶須要遍歷全部的entity,調用ipmi_domain_iterate_entities()函數並實現對應的handle_entity()回調函數就能夠。值得注意的是,用戶能夠經過枚舉函數ipmi_domain_iterate_xxxx的第三個參數 void * cb_data向回調函數傳遞參數,可是回調函數不能想上層帶回信息。
5. 調用OpenIPMI提供的函數來查詢sensor的狀態:OpenIPMI提供了大量的設置sensor和查詢sensor的函數,好比ipmi_is_state_set()、ipmi_set_initial_update_in_progress()等。用戶能夠直接調用這些函數來檢查某些狀態位或閾值位是否已經設置。
根據上面的分析咱們不難看到,藉助OpenIPMI提供的timer方法、回調機制和提供的諸多接口,用戶再也不須要對驅動、IPMI協議有詳盡瞭解,甚至也不用開發任何訪問BMC的函數,就能夠快速構建本身的SMS,這在產品更新換代日益加快的今天,無疑將會大大提升生產效率,加快產品上線進度。
框架