<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                學習Android硬件抽象層模塊的加載過程有助于理解它的編寫規范以及實現原理。Android系統中的硬件抽象層模塊是由系統統一加載的,當調用者需要加載這些模塊時,只要指定它們的ID值就可以了。 在Android硬件抽象層中,負責加載硬件抽象層模塊的函數是hw_get_module,它的原型如下: **hardware/libhardware/include/hardware/hardware.h** ~~~ /** * Get the module info associated with a module by id. * @return: 0 == success, <0 == error and *pHmi == NULL */ int hw_get_module(const char *id, const struct hw_module_t **module); ~~~ 它有id和module兩個參數。其中,id是輸入參數,表示要加載的硬件抽象層模塊ID;module是輸出參數,如果加載成功,那么它指向一個自定義的硬件抽象層模塊結構體。函數的返回值是一個整數,如果等于0,則表示加載成功;如果小于0,則表示加載失敗。 下面我們就開始分析hw_get_module函數的實現。 **hardware/libhardware/hardware.c** ~~~ /** Base path of the hal modules */ #define HAL_LIBRARY_PATH1 "/system/lib/hw" #define HAL_LIBRARY_PATH2 "/vendor/lib/hw" static const char *variant_keys[] = { "ro.hardware", /* This goes first so that it can pick up a different file on the emulator. */ "ro.product.board", "ro.board.platform", "ro.arch" }; static const int HAL_VARIANT_KEYS_COUNT = (sizeof(variant_keys)/sizeof(variant_keys[0])); int hw_get_module(const char *id, const struct hw_module_t **module) { int status; int i; const struct hw_module_t *hmi = NULL; char prop[PATH_MAX]; char path[PATH_MAX]; /* * Here we rely on the fact that calling dlopen multiple times on * the same .so will simply increment a refcount (and not load * a new copy of the library). * We also assume that dlopen() is thread-safe. */ /* Loop through the configuration variants looking for a module */ for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) { if (i < HAL_VARIANT_KEYS_COUNT) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH1, id, prop); if (access(path, R_OK) == 0) break; snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH2, id, prop); if (access(path, R_OK) == 0) break; } else { snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH1, id); if (access(path, R_OK) == 0) break; } } status = -ENOENT; if (i < HAL_VARIANT_KEYS_COUNT+1) { /* load the module, if this fails, we're doomed, and we should not try * to load a different variant. */ status = load(id, path, module); } return status; } ~~~ 在前面的2.3.1.1小節中,我們已經見過數組variant_keys的定義了,它用來組裝要加載的硬件抽象層模塊的文件名稱。常量HAL_VARIANT_KEYS_COUNT表示數組variant_keys的大小。 宏HAL_LIBRARY_PATH1和HAL_LIBRARY_PATH2用來定義要加載的硬件抽象層模塊文件所在的目錄。在前面的2.3.2小節中提到,編譯好的模塊文件位于out/target/product/generic/system/lib/hw目錄中,而這個目錄經過打包后,就對應于設備上的/system/lib/hw目錄。宏HAL_LIBRARY_PATH2所定義的目錄為/vendor/lib/hw,用來保存設備廠商所提供的硬件抽象層模塊接口文件。 函數第32行到第50行的for循環根據數組variant_keys在HAL_LIBRARY_PATH1和HAL_LIBRARY_PATH2目錄中檢查對應的硬件抽象層模塊文件是否存在,如果存在,則結束for循環;第56行調用load函數來執行加載硬件抽象層模塊的操作。 我們以在Android模塊器中加載硬件抽象層模塊freg為例,來分析硬件抽象層模塊的加載過程。在調用hw_get_module函數加載硬件抽象層模塊freg時,傳入的參數id的值為FREG_HARDWARE_MODULE_ID,即“freg”。在上面的for循環中,首先找到通過property_get函數獲得的系統屬性“ro.hardware”的值。在Android模擬器中,這個屬性的值定義為“goldfish”,于是通過第38和39兩行的snprintf函數,就得到變量path的值為“/system/lib/hw/freg.goldfish.so”。第40行調用access函數判斷文件/system/lib/hw/freg.goldfish.so是否存在,如果存在,就跳出循環;否則,再通過第42行到第44行的代碼來判斷文件/vendor/lib/hw/freg.goldfish.so是否存在,如果存在,那么也會跳出循環,因為要加載的硬件抽象層模塊文件已經找到了。如果這兩個文件都不存在,那么按照相同的方法來依次查找數組variant_keys中其他元素所對應的硬件抽象層模塊文件是否存在。如果數組variant_keys中的所有元素對應的硬件抽象層模塊文件都不存在,那么第46行到第48行的代碼就會在/system/lib/hw目錄中檢查是否存在一個freg.default.so文件。如果也不存在,那么硬件抽象層模塊freg的加載就失敗了。 找到了硬件抽象層模塊文件之后,第56行就調用load函數來執行硬件抽象層模塊的加載操作,它的實現如下所示。 **hardware/libhardware/hardware.c** ~~~ static int load(const char *id, const char *path, const struct hw_module_t **pHmi) { 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) { LOGE("load: id=%s != hmi->id=%s", id, hmi->id); status = -EINVAL; goto done; } hmi->dso = handle; /* 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; return status; } ~~~ 前面提到,硬件抽象層模塊文件實際上是一個動態鏈接庫文件,即so文件。因此,第14行調用dlopen函數將它加載到內存中。加載完成這個動態鏈接庫文件之后,第24行就調用dlsym函數來獲得里面名稱為HAL_MODULE_INFO_SYM_AS_STR的符號。這個HAL_MODULE_INFO_SYM_AS_STR符號指向的是一個自定義的硬件抽象層模塊結構體,它包含了對應的硬件抽象層模塊的所有信息。HAL_MODULE_INFO_SYM_AS_STR是一個宏,它的值定義為“HMI”。根據硬件抽象層模塊的編寫規范,每一個硬件抽象層模塊都必須包含一個名稱為“HMI”的符號,而且這個符號的第一個成員變量的類型必須定義為hw_module_t,因此,第24行可以安全地將模塊中的HMI符號轉換為一個hw_module_t結構體指針。 獲得了這個hw_module_t結構體指針之后,第32行調用strcmp函數來驗證加載得到的硬件抽象層模塊ID是否與所要求加載的硬件抽象層模塊ID一致。如果不一致,就說明出錯了,函數返回一個錯誤值-EINVAL。最后,第38行將成功加載后得到的模塊句柄值handle保存在hw_module_t結構體指針hmi的成員變量dso中,然后將它返回給調用者。 至此,硬件抽象層模塊的加載過程就介紹完了。接下來,我們分析在硬件抽象層模塊的加載過程中,經常會碰到的一個權限問題,即無法調用open函數打開對應的設備文件。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看