Android硬件抽象層(HAL)深刻剖析(三)【轉】

前面分析了android HAL層是如何搜索硬件模塊的動態共享庫的,其實就是在"system/lib/hw/"或者"/vendor/lib/hw/"這兩個路徑下找到共享庫modueid.variant.so後,經過調用load函數加載庫。android

下面咱們進入load函數,看看具體是如何實現加載共享庫的。架構

如下爲load函數定義,一樣在/hardware/libhardware/hardware.c中實現的。函數

/**
 * Load the file defined by the variant and if successful
 * return the dlopen handle and the hmi.
 * @return 0 = success, !0 = failure.
 */
static int load(const char *id,
        const char *path,
        const struct hw_module_t **pHmi)
{//傳入硬件模塊id和庫所在路徑,獲取到硬件模塊結構體
    int status;
    void *handle;
    struct hw_module_t *hmi;

    /*
     * load the symbols resolving undefined symbols before
     * dlopen returns. Since RTLD_GLOBAL is not or'd in with
     * RTLD_NOW the external symbols will not be global
     */
    handle = dlopen(path, RTLD_NOW);//打開共享庫
    if (handle == NULL) {
        char const *err_str = dlerror();
        LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
        status = -EINVAL;
        goto done;
    }

    /* Get the address of the struct hal_module_info. */
    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
    hmi = (struct hw_module_t *)dlsym(handle, sym);//解析共享庫
    if (hmi == NULL) {
        LOGE("load: couldn't find symbol %s", sym);
        status = -EINVAL;
        goto done;
    }

    /* Check that the id matches */
    if (strcmp(id, hmi->id) != 0) {//匹配解析出硬件模塊的id和傳入咱們實際想要獲得的模塊id是否一致
        LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
        status = -EINVAL;
        goto done;
    }

    hmi->dso = handle;  //將打開庫獲得句柄傳給硬件模塊的dso

    /* success */
    status = 0;

    done:
    if (status != 0) {
        hmi = NULL;
        if (handle != NULL) {
            dlclose(handle);
            handle = NULL;
        }
    } else {
        LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
                id, path, *pHmi, handle);
    }

    *pHmi = hmi;//將獲得的module的結果經過第三個參數傳給hw_module_t

    return status;
}

能夠看到load函數傳入的幾個參數,第一個參數就是須要加載的硬件模塊對應動態庫的硬件模塊的id,spa

第二個參數就是動態庫存放的路徑,就是在hw_get_module函數前部分搜索庫獲得的path,指針

第三個參數就是咱們須要獲得的硬件模塊結構體,經過它傳給hw_get_module,hw_get_module函數在經過參數傳給jni。code

第19行,首先調用dlopen打開共享庫,該函數經過傳入的庫的路徑找到庫,而且打開它,傳回一個操做句柄handle,而後再調用dlsym函數解析這個打開的庫,下面第29行,獲得庫中包含的硬件模塊結構體,並將它返回回來。因此硬件廠商或者硬件移植者都必須根據hal的這個架構去實現填充這個和本身硬件相關的硬件模塊結構體hw_module_t,供使用。blog

經過dlsym解析以後就獲得了hw_module_t,隨後第37行,將從庫中解析獲得的結構體中的id和傳入的id作比較,看是否一致。get

若是一致則證實就是獲得正確的硬件模塊了。it

最後第60行,將hw_module_t結構體指針傳給第三個參數,傳給hw_get_module函數。class

到此,hw_get_module函數就獲得了硬件模塊結構體hw_module_t.

有了hw_module_t,那麼經過其內部的method open就能打開硬件模塊對應的設備了,經過結構體中的一些方法就能操做硬件設備了。

相關文章
相關標籤/搜索