c語言下的工廠模式——ipmi源碼分析

字號:

IPMItool的架構(gòu)
    ==============
    源碼目錄如下
     +---contrib //用于建立web管理頁面的shell腳本
     +---control //包含一些安裝、配置信息
     +---debian //包含changelog等信息
     +---doc //man的幫助信息
     +---include
     | \---ipmitool //頭文件定義
     +---lib //對IPMI規(guī)范的對應(yīng)實現(xiàn),如ipmi_session.c處理session
     \---src //此目錄下是ipmitool的三個主程序
     \---plugins // ipmi_intf.c interface一些通用功能的實現(xiàn)
     +---bmc // ipmitool與bmc kernel driver之間的接口
     +---imb // Intel IMB Interface
     +---lan // IPMI v1.5 LAN Interface
     +---lanplus // IPMI v2.0 RMCP+ LAN Interface
     +---lipmi // Solaris x86 LIPMI interface
     \---open // Linux OpenIPMI Interface [default]
    C語言下的工廠模式
    =================
    從上述的目錄結(jié)構(gòu)不難看出,IPMItool設(shè)計上的一個重要特色就是將不同的interface看作plugin。從而使系統(tǒng)具有清晰的結(jié)構(gòu)和良好的擴充性。
    IPMI規(guī)范中定義的實體,如session,fru,sdr,chassis,sensor等等,都在lib中做對應(yīng)的實現(xiàn)。這部分是與具體interface相分離的。interface的通用接口在include\ipmitool\ipmi_intf.h中定義;interface的通用功能實現(xiàn),在\src\plugins\ipmi_intf.c中。值得注意的是,interface是IPMI規(guī)范中定義的概念,普通意義上的接口本文中均使用中文“接口”。
    這種將通用接口與具體實現(xiàn)相分離的方式無疑就是一種簡單工廠模式了。
    實踐
    ====
    那么interface具體是怎么實現(xiàn)為plugin的呢?可以從一個具體的例子看一下。
    include\ipmitool\ipmi_intf.h中用ipmi_intf定義了了
     struct ipmi_intf {
     ...
     struct ipmi_session * session;
     struct ipmi_oem_handle * oem;
     uint32_t my_addr;
     uint32_t target_addr;
     int (*setup)(struct ipmi_intf * intf);
     int (*open)(struct ipmi_intf * intf);
     void (*close)(struct ipmi_intf * intf);
     ...
     };
    與OO語言類似,struct內(nèi)部定義了數(shù)據(jù)和方法。不同的是,方法采用的是函數(shù)指針的方式。因為沒有this指針,所以函數(shù)的形參就是指向自身struct的指針。如setup。
    而在具體實現(xiàn)中,如src\plugins\lan\lan.c中給出了具體的函數(shù)實現(xiàn)。如ipmi_lan_setup。在ipmi_lan_setup中,即可使用形參定義的intf指針實現(xiàn)對ipmi_intf結(jié)構(gòu)中相應(yīng)數(shù)據(jù)的操作。
    struct ipmi_intf ipmi_lan_intf = {
     name: "lan",
     desc: "IPMI v1.5 LAN Interface",
     setup: ipmi_lan_setup,
     open: ipmi_lan_open,
     close: ipmi_lan_close,
     sendrecv: ipmi_lan_send_cmd,
     sendrsp: ipmi_lan_send_rsp,
     keepalive: ipmi_lan_keepalive,
     target_addr: IPMI_BMC_SLAVE_ADDR,
    };