 Android硬件抽(chou)象(xiang)層(ceng)(HAL)深入剖析(xi)(三)
							時間:2018-09-26      來(lai)源:未知
							Android硬件抽(chou)象(xiang)層(ceng)(HAL)深入剖析(xi)(三)
							時間:2018-09-26      來(lai)源:未知 
							前面(mian)分(fen)析了android HAL層是如何搜索硬(ying)件模(mo)塊的(de)動態共享(xiang)庫(ku)(ku)的(de),其實就(jiu)是在(zai)"system/lib/hw/"或(huo)者"/vendor/lib/hw/"這兩個路徑(jing)下找到共享(xiang)庫(ku)(ku)modueid.variant.so后,通(tong)過調(diao)用load函數加載庫(ku)(ku)。
下(xia)面我(wo)們進入load函數,看看具體是(shi)如(ru)何(he)實現加載(zai)共(gong)享庫的。
以下為(wei)load函數定義,同樣在(zai)/hardware/libhardware/hardware.c中實現(xian)的。
1 /**
2 * Load the file defined by the variant and if successful
3 * return the dlopen handle and the hmi.
4 * @return 0 = success, !0 = failure.
5 */
6 static int load(const char *id,
7 const char *path,
8 const struct hw_module_t **pHmi)
9 {//傳入硬件模(mo)塊(kuai)id和庫所在(zai)路徑,獲取到硬件模(mo)塊(kuai)結(jie)構體
10 int status;
11 void *handle;
12 struct hw_module_t *hmi;
13
14 /*
15 * load the symbols resolving undefined symbols before
16 * dlopen returns. Since RTLD_GLOBAL is not or'd in with
17 * RTLD_NOW the external symbols will not be global
18 */
19 handle = dlopen(path, RTLD_NOW);//打開共享庫
20 if (handle == NULL) {
21 char const *err_str = dlerror();
22 LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
23 status = -EINVAL;
24 goto done;
25 }
26
27 /* Get the address of the struct hal_module_info. */
28 const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
29 hmi = (struct hw_module_t *)dlsym(handle, sym);//解析共享庫
30 if (hmi == NULL) {
31 LOGE("load: couldn't find symbol %s", sym);
32 status = -EINVAL;
33 goto done;
34 }
35
36 /* Check that the id matches */
37 if (strcmp(id, hmi->id) != 0) {//匹配(pei)解析(xi)出硬件模(mo)塊(kuai)的(de)id和傳入(ru)我們實際(ji)想要得(de)到的(de)模(mo)塊(kuai)id是否一致
38 LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
39 status = -EINVAL;
40 goto done;
41 }
42
43 hmi->dso = handle; //將打開(kai)庫(ku)得到(dao)句柄傳給(gei)硬件(jian)模塊的dso
44
45 /* success */
46 status = 0;
47
48 done:
49 if (status != 0) {
50 hmi = NULL;
51 if (handle != NULL) {
52 dlclose(handle);
53 handle = NULL;
54 }
55 } else {
56 LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
57 id, path, *pHmi, handle);
58 }
59
60 *pHmi = hmi;//將得到的module的結果通(tong)過第三個參(can)數傳(chuan)給(gei)hw_module_t
61
62 return status;
63 }
可(ke)以看(kan)到load函(han)數傳入(ru)的(de)幾個(ge)參(can)數,第一個(ge)參(can)數就是需要加載的(de)硬(ying)件(jian)模(mo)塊對應動態庫的(de)硬(ying)件(jian)模(mo)塊的(de)id;
第二個(ge)參數就是(shi)(shi)動態庫存放的路徑,就是(shi)(shi)在hw_get_module函數前(qian)部分搜索庫得到的path;
第(di)三個參(can)數就是我們需要得(de)到的硬件模(mo)塊結(jie)構體,通(tong)過它傳給(gei)(gei)hw_get_module,hw_get_module函(han)數在通(tong)過參(can)數傳給(gei)(gei)jni。
第(di)19行,首先調用dlopen打開共享庫(ku)(ku),該函(han)(han)數通過傳入的(de)(de)庫(ku)(ku)的(de)(de)路(lu)徑找到(dao)(dao)庫(ku)(ku),并且打開它(ta),傳回(hui)一個(ge)操作句柄handle,然后再調用dlsym函(han)(han)數解(jie)析這個(ge)打開的(de)(de)庫(ku)(ku),下面(mian)第(di)29行,得到(dao)(dao)庫(ku)(ku)中包含的(de)(de)硬件(jian)模塊結構體,并將它(ta)返回(hui)回(hui)來。所以硬件(jian)廠商(shang)或者(zhe)硬件(jian)移(yi)植者(zhe)都(dou)必須根據hal的(de)(de)這個(ge)架(jia)構去(qu)實現填充這個(ge)和自(zi)己硬件(jian)相(xiang)關的(de)(de)硬件(jian)模塊結構體hw_module_t,供使用。
通過dlsym解析之(zhi)后就得到(dao)了hw_module_t,隨后第37行,將從庫中解析得到(dao)的結構體中的id和傳入的id做比(bi)較,看是否一致。
如果一致則(ze)證明就是(shi)得(de)到正確的硬件(jian)模塊了。
后(hou)第(di)60行,將hw_module_t結(jie)構體指針傳給第(di)三個參數,傳給hw_get_module函數。
到(dao)此,hw_get_module函(han)數就得到(dao)了硬(ying)件模塊結構體hw_module_t.
有了hw_module_t,那么通過其(qi)內部的method open就能打(da)開硬件模(mo)塊(kuai)對應的設(she)備了,通過結構體中的一(yi)些方法就能操作硬件設(she)備了。

