需要啟動(dòng)Android驅(qū)動(dòng)模塊Makefile編寫。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、網(wǎng)站空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、察布查爾錫伯網(wǎng)站維護(hù)、網(wǎng)站推廣。
PCI是一種外設(shè)總線規(guī)范。我們先來看一下什么是總線:總線是一種傳輸信號(hào)的路徑或信道。典型情況是,總線是連接于一個(gè)或多個(gè)導(dǎo)體的電氣連線,總線上連接的所有設(shè)備可在同一時(shí)間收到所有的傳輸內(nèi)容??偩€由電氣接口和編程接口組成。本文討論Linux 下的設(shè)備驅(qū)動(dòng),所以,重點(diǎn)關(guān)注編程接口。
CI是Peripheral Component Interconnect(外圍設(shè)備互聯(lián))的簡(jiǎn)稱,是普遍使用在桌面及更大型的計(jì)算機(jī)上的外設(shè)總線。PCI架構(gòu)被設(shè)計(jì)為ISA標(biāo)準(zhǔn)的替代品,他有三個(gè)主要目標(biāo):獲得在計(jì)算機(jī)和外設(shè)之間傳輸數(shù)據(jù)時(shí)更好的性能;盡可能的平臺(tái)無關(guān);簡(jiǎn)化往系統(tǒng)中添加和刪除外設(shè)的工作。
解壓后應(yīng)該有各個(gè)操作系統(tǒng)的驅(qū)動(dòng),這個(gè)驅(qū)動(dòng)是INF格式,不是setup,需要手動(dòng)安裝,在設(shè)備管理器里選擇未知設(shè)備,雙擊選擇驅(qū)動(dòng)程序,然后選更新驅(qū)動(dòng)程序,指定你驅(qū)動(dòng)存放的文件即可
上一篇文章,在解析初始化GraphicBuffer中,遇到一個(gè)ion驅(qū)動(dòng),對(duì)圖元進(jìn)行管理。首先看看ion是怎么使用的:
我們按照這個(gè)流程分析ion的源碼。
如果對(duì)ion使用感興趣,可以去這篇文章下面看
本文基于Android的Linux內(nèi)核版本3.1.8
遇到什么問題歡迎來本文討論
什么是ion?如果是音視頻,Camera的工程師會(huì)對(duì)這個(gè)驅(qū)動(dòng)比較熟悉。最早的GPU和其他驅(qū)動(dòng)協(xié)作申請(qǐng)一塊內(nèi)存進(jìn)行繪制是使用比較粗暴的共享內(nèi)存。在Android系統(tǒng)中使用的是匿名內(nèi)存。最早由三星實(shí)現(xiàn)了一個(gè)Display和Camera共享內(nèi)存的問題,曾經(jīng)在Linux社區(qū)掀起過一段時(shí)間。之后各路大牛不斷的改進(jìn)之下,就成為了dma_buf驅(qū)動(dòng)。并在 Linux-3.3 主線版本合入主線?,F(xiàn)在已經(jīng)廣泛的運(yùn)用到各大多媒體開發(fā)中。
首先介紹dma_buf的2個(gè)角色,importer和exporter。importer是dma_buf驅(qū)動(dòng)中的圖元消費(fèi)者,exporter是dma_buf驅(qū)動(dòng)中的圖元生產(chǎn)者。
這里借用大佬的圖片:
ion是基于dma_buf設(shè)計(jì)完成的。經(jīng)過閱讀源碼,其實(shí)不少思路和Android的匿名內(nèi)存有點(diǎn)相似。閱讀本文之前就算不知道dma_buf的設(shè)計(jì)思想也沒關(guān)系,我不會(huì)仔細(xì)到每一行,我會(huì)注重其在gralloc服務(wù)中的申請(qǐng)流程,看看ion是如何管理共享內(nèi)存,為什么要拋棄ashmem。
我們先來看看ion的file_operation:
只有一個(gè)open和ioctl函數(shù)。但是沒有mmap映射。因此mmap映射的時(shí)候一定其他對(duì)象在工作。
我們關(guān)注顯卡英偉達(dá)的初始化模塊。
文件:/ drivers / staging / android / ion / tegra / tegra_ion.c
module_platform_driver實(shí)際上就是我之前經(jīng)常提到過的module_init的一個(gè)宏,多了一個(gè)register注冊(cè)到對(duì)應(yīng)名字的平臺(tái)中的步驟。在這里面注冊(cè)了一個(gè)probe方法指針,probe指向的tegra_ion_probe是加載內(nèi)核模塊注冊(cè)的時(shí)候調(diào)用。
先來看看對(duì)應(yīng)的結(jié)構(gòu)體:
再來看看對(duì)應(yīng)ion內(nèi)的堆結(jié)構(gòu)體:
完成的事情如下幾個(gè)步驟:
我們不關(guān)注debug模式。其實(shí)整個(gè)就是我們分析了很多次的方法。把這個(gè)對(duì)象注冊(cè)miscdevice中。等到insmod就會(huì)把整個(gè)整個(gè)內(nèi)核模塊從dev_t的map中關(guān)聯(lián)出來。
我們來看看這個(gè)驅(qū)動(dòng)結(jié)構(gòu)體:
文件:/ drivers / staging / android / ion / ion_heap.c
這里有四個(gè)不同堆會(huì)申請(qǐng)出來,我們主要來看看默認(rèn)的ION_HEAP_TYPE_SYSTEM對(duì)應(yīng)的heap流程。
其實(shí)真正象征ion的內(nèi)存堆是下面這個(gè)結(jié)構(gòu)體
不管原來的那個(gè)heap,會(huì)新建3個(gè)ion_system_heap,分別order為8,4,0,大于4為大內(nèi)存。意思就是這個(gè)heap中持有一個(gè)ion_page_pool 頁(yè)資源池子,里面只有對(duì)應(yīng)order的2的次冪,內(nèi)存塊。其實(shí)就和伙伴系統(tǒng)有點(diǎn)相似。
還會(huì)設(shè)置flag為ION_HEAP_FLAG_DEFER_FREE,這個(gè)標(biāo)志位后面會(huì)用到。
文件:/ drivers / staging / android / ion / ion_page_pool.c
在pool中分為2個(gè)鏈表一個(gè)是high_items,另一個(gè)是low_items。他們之間的區(qū)分在此時(shí)就是以2為底4的次冪為分界線。
文件:/ drivers / staging / android / ion / ion.c
因?yàn)榇蜷_了標(biāo)志位ION_HEAP_FLAG_DEFER_FREE和heap存在shrink方法。因此會(huì)初始化兩個(gè)回收函數(shù)。
文件:/ drivers / staging / android / ion / ion_heap.c
此時(shí)會(huì)創(chuàng)建一個(gè)內(nèi)核線程,調(diào)用ion_heap_deferred_free內(nèi)核不斷的循環(huán)處理。不過由于這個(gè)線程設(shè)置的是SCHED_IDLE,這是最低等級(jí)的時(shí)間片輪轉(zhuǎn)搶占。和Handler那個(gè)adle一樣的處理規(guī)則,就是閑時(shí)處理。
在這個(gè)循環(huán)中,不斷的循環(huán)銷毀處理heap的free_list里面已經(jīng)沒有用的ion_buffer緩沖對(duì)象。
文件:/ drivers / staging / android / ion / ion_system_heap.c
注冊(cè)了heap的銷毀內(nèi)存的方法。當(dāng)系統(tǒng)需要銷毀頁(yè)的時(shí)候,就會(huì)調(diào)用通過register_shrinker注冊(cè)進(jìn)來的函數(shù)。
文件:/ drivers / staging / android / ion / ion_page_pool.c
整個(gè)流程很簡(jiǎn)單,其實(shí)就是遍歷循環(huán)需要銷毀的頁(yè)面數(shù)量,接著如果是8的次冪就是移除high_items中的page緩存。4和0則銷毀low_items中的page緩存。至于為什么是2的次冪其實(shí)很簡(jiǎn)單,為了銷毀和申請(qǐng)簡(jiǎn)單。__free_pages能夠整頁(yè)的銷毀。
文件:/ drivers / staging / android / ion / ion.c
主要就是初始化ion_client各個(gè)參數(shù),最后把ion_client插入到ion_device的clients。來看看ion_client結(jié)構(gòu)體:
核心還是調(diào)用ion_alloc申請(qǐng)一個(gè)ion緩沖區(qū)的句柄。最后把數(shù)據(jù)拷貝會(huì)用戶空間。
這個(gè)實(shí)際上就是找到最小能承載的大小,去申請(qǐng)內(nèi)存。如果8kb申請(qǐng)內(nèi)存,就會(huì)拆分積分在0-4kb,4kb-16kb,16kb-128kb區(qū)間找。剛好dma也是在128kb之內(nèi)才能申請(qǐng)。超過這個(gè)數(shù)字就禁止申請(qǐng)。8kb就會(huì)拆成2個(gè)4kb保存在第一個(gè)pool中。
最后所有的申請(qǐng)的page都添加到pages集合中。
文件:/ drivers / staging / android / ion / ion_page_pool.c
能看到此時(shí)會(huì)從 ion_page_pool沖取出對(duì)應(yīng)大小區(qū)域的空閑頁(yè)返回上層,如果最早的時(shí)候沒有則會(huì)調(diào)用ion_page_pool_alloc_pages申請(qǐng)一個(gè)新的page。由于引用最終來自ion_page_pool中,因此之后申請(qǐng)之后還是在ion_page_pool中。
這里的處理就是為了避免DMA直接內(nèi)存造成的緩存差異(一般的申請(qǐng),默認(rèn)會(huì)帶一個(gè)DMA標(biāo)志位)。換句話說,是否打開cache其實(shí)就是,關(guān)閉了則使用pool的cache,打開了則不使用pool緩存,只依賴DMA的緩存。
我們可以看另一個(gè)dma的heap,它是怎么做到dma內(nèi)存的一致性.
文件: drivers / staging / android / ion / ion_cma_heap.c
能看到它為了能辦到dma緩存的一致性,使用了dma_alloc_coherent創(chuàng)建了一個(gè)所有強(qiáng)制同步的地址,也就是沒有DMA緩存的地址。
這里出現(xiàn)了幾個(gè)新的結(jié)構(gòu)體,sg_table和scatterlist
文件:/ lib / scatterlist.c
這里面實(shí)際上做的事情就是一件:初始化sg_table.
sg_table中有一個(gè)核心的對(duì)象scatterlist鏈表。如果pages申請(qǐng)的對(duì)象數(shù)量PAGE_SIZE/sizeof(scatterlist),每一項(xiàng)sg_table只有一個(gè)scatterlist。但是超出這個(gè)數(shù)字就會(huì)增加一個(gè)scatterlist。
用公式來說:
換句話說,每一次生成scatterlist的鏈表就會(huì)直接盡可能占滿一頁(yè),讓內(nèi)存更好管理。
返回了sg_table。
初始化ion_handle,并且記錄對(duì)應(yīng)的ion_client是當(dāng)前打開文件的進(jìn)程,并且設(shè)置ion_buffer到handle中。使得句柄能夠和buffer關(guān)聯(lián)起來。
每當(dāng)ion_buffer需要銷毀,
一、手機(jī)開機(jī)狀態(tài)的驅(qū)動(dòng)安裝
現(xiàn)在手機(jī)處于開機(jī)狀態(tài)(打開USB調(diào)試并且授權(quán)電腦進(jìn)行調(diào)試)連接電腦.
右鍵計(jì)算機(jī)-屬性-選擇左上角的
設(shè)備管理器
找到
其他設(shè)備
有個(gè)帶著黃色感嘆號(hào)的Android設(shè)備(如下圖),這就是你的一加手機(jī),win8.1的系統(tǒng)無法自己安裝...
右鍵該設(shè)備
選擇"更新驅(qū)動(dòng)程序軟件"
選擇"瀏覽計(jì)算機(jī)以查找驅(qū)動(dòng)程序軟件"
瀏覽,將其定位在"C:\Program
Files\ONEPLUS\USB
Driver\"目錄,下一步,即可完成第一部分的驅(qū)動(dòng).
等待安裝完成后,電腦"設(shè)備管理器"可以看到,出現(xiàn)了"Android
Composite
ADB
interface":
二、Bootloader狀態(tài)的驅(qū)動(dòng)安裝
手機(jī)斷開數(shù)據(jù)線,關(guān)機(jī).
關(guān)機(jī)狀態(tài)下,按住"開始鍵+音量上鍵",進(jìn)入Fastboot.此時(shí)重新連接電腦.
在這里,選擇"設(shè)備管理器-查看-顯示隱藏的驅(qū)動(dòng)".
這個(gè)驅(qū)動(dòng)能自己安裝,等待安裝完成后,電腦"設(shè)備管理器"可以看到,出現(xiàn)了"Android
Bootloader
interface":
三、Recovery狀態(tài)的驅(qū)動(dòng)安裝
手機(jī)斷開數(shù)據(jù)線,按住關(guān)機(jī)鍵5S,強(qiáng)制關(guān)機(jī).
關(guān)機(jī)狀態(tài)下,按住"開始鍵+音量下鍵",進(jìn)入Recovery.此時(shí)重新連接電腦
在電腦的"設(shè)備管理器-其他設(shè)備"又能找到帶黃色嘆號(hào)的設(shè)備,右鍵它,選擇"更新驅(qū)動(dòng)程序軟件"
這次需要選擇"從計(jì)算機(jī)的設(shè)備驅(qū)動(dòng)程序列表中選取"(也就是下面那個(gè)選項(xiàng))
到了下面的界面,選擇Android
Phone(電腦上有兩個(gè),一個(gè)不能用,所以不行的話是另外一個(gè))
這下看到了
Oneplus,點(diǎn)擊選擇,然后下一步,完成安裝.