亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        Android系統(tǒng)動(dòng)態(tài)調(diào)試技術(shù)

        2019-07-12 08:28:26張恩勤姜德軍程雯吳海全
        電子技術(shù)與軟件工程 2019年9期
        關(guān)鍵詞:內(nèi)核日志代碼

        文/張恩勤 姜德軍 程雯 吳海全

        1 簡介

        Android是目前最為廣泛應(yīng)用的一個(gè)嵌入式操作系統(tǒng),手機(jī)、平板電腦和汽車等電子等各種設(shè)備中皆可見其身影。根據(jù)IDC的統(tǒng)計(jì),2018年Android在移動(dòng)平臺的市場占有率為85%,而且預(yù)期未來5年內(nèi)還將保持1.7%的年增長率,越來越多的Android的設(shè)備以及應(yīng)用程序在被開發(fā)出來。如何在Android這么一個(gè)大的系統(tǒng)中調(diào)試這些新的設(shè)備驅(qū)動(dòng)或者應(yīng)用程序一直是開發(fā)過程中的一個(gè)重要問題。一個(gè)優(yōu)秀的方法將有效節(jié)約我們的開發(fā)時(shí)間和開發(fā)費(fèi)用。

        這是一個(gè)典型的傳統(tǒng)的軟件調(diào)試過程:

        (1)在App1中發(fā)現(xiàn)一個(gè)問題。

        (2)調(diào)整App1的源程序,添加調(diào)試代碼。

        (3)重新編譯App1并加載到設(shè)備中。

        (4)復(fù)現(xiàn)App1問題,取得對應(yīng)的調(diào)試信息。

        (5)分析發(fā)現(xiàn)App1的問題是由于App1中使用了DriverA。

        (6)修過DriverA的源程序,加入打開調(diào)試信息。

        (7)重新編譯DriverA并加載到設(shè)備中。

        (8)復(fù)現(xiàn)DriverA問題,取得對應(yīng)的調(diào)試信息。

        (9)發(fā)現(xiàn)DriverA的問題又是由其調(diào)用DriverB引起...

        這個(gè)過程我們發(fā)現(xiàn)很多時(shí)間被浪費(fèi)在修改代碼增加日志、重新編譯,加載目標(biāo)程序到設(shè)備等操作中。這里會有這樣一個(gè)疑問,為什么我們不一次打開所有涉及模塊的調(diào)試信息呢?如果我們用這種方法,我們會一次獲得非常大量的信息,對于我們分析問題會不方便,而且過度的調(diào)試信息可能會改變程序的運(yùn)行時(shí)序,使得問題沒法重現(xiàn)。

        是否可以在不修改程序的情況下動(dòng)態(tài)打開關(guān)閉調(diào)試日志呢,其實(shí)Android內(nèi)核有一種動(dòng)態(tài)調(diào)試技術(shù)。pr_debug()或者dev_debug()來代替?zhèn)鹘y(tǒng)的printk()輸出日志。內(nèi)核通過他們可以在運(yùn)行期動(dòng)態(tài)地打開關(guān)閉調(diào)試信息。

        這是一個(gè)典型的基于動(dòng)態(tài)調(diào)試技術(shù)的調(diào)試軟件過程:

        (1)在App1中發(fā)現(xiàn)一個(gè)問題。

        (2)運(yùn)行命令打開App1的調(diào)試信息。

        (3)復(fù)現(xiàn)App1問題,取得對應(yīng)的調(diào)試信息。

        (4)分析發(fā)現(xiàn)App1的問題是由于App1中使用了DriverA。

        (5)運(yùn)行命令打開DriverA的調(diào)試信息,同時(shí)如果需要可以關(guān)閉App1的的調(diào)試信息。

        (6)復(fù)現(xiàn)DriverA問題,取得對應(yīng)的調(diào)試信息。

        (7)發(fā)現(xiàn)DriverA的問題又是由其調(diào)用DriverB引起。

        (8)運(yùn)行命令打開DriverB的調(diào)試信息...

        顯而易見,通過這種方法可以使我們的調(diào)試過程更加有效率。我們下面了解一下動(dòng)態(tài)調(diào)試技術(shù)如何在Android內(nèi)核中使用,然后拓展這個(gè)技術(shù)到用戶態(tài)程序。

        2 動(dòng)態(tài)調(diào)試在Andoird核心模塊中的使用方法

        Android內(nèi)核模塊中使用的動(dòng)態(tài)調(diào)試技術(shù)基于Linux DebugFS。DebugFS是一個(gè)虛擬的內(nèi)存文件系統(tǒng),和procFS以及sysFS類似.可以用來在用戶空間和內(nèi)核模塊之間交換數(shù)據(jù)。

        首先,編譯時(shí)需要確定內(nèi)核配置文件中的DebugFS和Dynamic debug是打開的。

        接著,就可以在開發(fā)內(nèi)核模塊的過程中使用 pr_debug()或者dev_debug()代替printk(),預(yù)先在關(guān)鍵點(diǎn)加上各種打印日志。

        運(yùn)行調(diào)試時(shí),首先確認(rèn)debugFS被加載,加載方式可以通過為init.rc腳本增加命令,或者在啟動(dòng)以后直接運(yùn)行如下命令:

        mount -t debugfs debugfs /sys/kernel/debug

        當(dāng)執(zhí)行過以上命令后,我們可以在調(diào)試目標(biāo)的文件系統(tǒng)中發(fā)現(xiàn)如下文件:

        /sys/kernel/debug/dynamic_debug/control

        這時(shí)pr_debug()或者dev_debug()的行為就會為這個(gè)文件所控制,開發(fā)者可以通過修改這個(gè)文件來控制調(diào)試日志是否輸出。默認(rèn)情況下所有的調(diào)試開關(guān)是關(guān)閉的,只有CONFIG_DYNAMIC_DΕBUG打開時(shí)才會建立這一文件,對于非調(diào)試階段程序運(yùn)行效率的影響非常小。

        每一個(gè)日志都可以被單獨(dú)控制或者從更高層統(tǒng)一控制。例如打開一個(gè)模塊中的所有打印日志、一個(gè)文件中的所有打印日志、一個(gè)函數(shù)所有打印日志或者僅有指定的一行的日志。

        例如:

        通過這種方法我們可以在程序運(yùn)行期打開我們需要的信息,同樣,通過把以上命令中的“+p”變?yōu)椤?p”。我們可以動(dòng)態(tài)關(guān)掉調(diào)試信息。

        比如關(guān)svc_process()函數(shù)的所有信息

        # echo -n 'func svc_process -p' >/sys/kernel/debug/dynamic_debug/control

        3 動(dòng)態(tài)調(diào)試如何運(yùn)行

        這個(gè)章節(jié)我們走進(jìn)Android內(nèi)核代碼,具體分析動(dòng)態(tài)調(diào)試技術(shù)是如何運(yùn)行的。dev_dbg()和pr_debug()運(yùn)行基本一樣,我們使用pr_debug()作為例子。

        如果DΕBUG被定義,我們就會繼續(xù)使用printk。如果DΕBUG和CONFIG_DYNAMIC_DΕBUG都沒有被定義,目標(biāo)代碼就不保護(hù)任何調(diào)試信息。這兒我們關(guān)注dynamic_pr_debug()。

        在dynamic_debug.h里面:

        Unlikely ()在這里的使用是為了在調(diào)試沒有打開時(shí)獲得更好的運(yùn)行效率。GCC編譯器會根據(jù)unlikely()做優(yōu)化,把調(diào)試相關(guān)代碼放到跳轉(zhuǎn)語句中,因?yàn)楦嗟那闆r是調(diào)試不打開的情況。

        在對應(yīng)模塊的makef i le文件中定義了DΕBUG_HASH 和 DΕBUG_HASH2。 使 用djb2和r5哈希算法。輸入?yún)?shù)為代碼的路徑,模塊名稱。這兩個(gè)哈希值用了加速判斷某一個(gè)模塊的調(diào)試是打開還是關(guān)閉。

        debug_f l ags =

        -D"DΕBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"

        -D"DΕBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"

        可以發(fā)現(xiàn)當(dāng)源程序被編譯后,每一個(gè)使用pr_debug()語句的地方,目標(biāo)代碼中會插入一個(gè)_ddebug的結(jié)構(gòu)體,名為descriptor,放入__verbose數(shù)據(jù)段。它包含所有調(diào)試相關(guān)信息,比如模塊名稱函數(shù)名稱、文件名、DΕBUG_HASH DΕBUG_HASH2和調(diào)試標(biāo)志。換一種說法,每一使用pr_debug()的地方,可執(zhí)行代碼中都會這么一段。

        更加深入一些,我們解釋開一段二進(jìn)制代碼,就會發(fā)現(xiàn)__verbose數(shù)據(jù)段有這樣的數(shù)據(jù):

        0e38 72020000 00000000 7b020000 b8020000 0d0f0000 26010000

        0e50 72020000 1c000000 7b020000 b8020000 0d0f0000 5f010000

        可以發(fā)現(xiàn)其實(shí)這就是_ddebug數(shù)據(jù)。

        同時(shí)Android內(nèi)核中有個(gè)dynamic_debug模塊,當(dāng)系統(tǒng)啟動(dòng)起來的時(shí)候會被調(diào)用。創(chuàng)建一個(gè)名為control的debugFS。

        在dynamic_debug.c里面:

        dynamic_debug用于創(chuàng)建和維持一個(gè)名為debug_tables的鏈表。同時(shí)創(chuàng)建了兩個(gè)哈希表,用于加速查詢過程。(和前面介紹的一樣,使用路徑和模塊名稱作為key)。

        當(dāng)使用pr_debug()的被調(diào)試程序裝載的時(shí)候,動(dòng)態(tài)調(diào)試模塊會裝載位于__verbose數(shù)據(jù)段的數(shù)據(jù),分析并存到鏈表中。從這張表里面可以看出多少pr_debug()是出于打開狀況的。

        在module.c里面,當(dāng)一個(gè)內(nèi)核模塊安裝時(shí)候以下函數(shù)會被調(diào)用。所有驅(qū)動(dòng)模塊的_verbose數(shù)據(jù)段都會被用來初始化debug_tables。

        任何用戶對debugFS “control”的寫操作都會導(dǎo)致ddebug_change ()被調(diào)用。相應(yīng)的 debug_tables、 dynamic_debug_enabled 和dynamic_debug_enabled2會被改動(dòng)。

        以打開調(diào)試為例,這三個(gè)變量會賦值為True,從而前文提到的pr_debug()里面的__dynamic_dbg_enabled()函數(shù)中所有判斷條件都滿足,__dynamic_dbg_enabled()返回真,調(diào)試消息被打印出。

        4 用戶空間的動(dòng)態(tài)技術(shù)

        在用戶空間里面沒有內(nèi)核里面的這個(gè)預(yù)先定義的動(dòng)態(tài)調(diào)試模塊,但是當(dāng)我們理解了其運(yùn)行模式,我們可以運(yùn)用相似的方法來進(jìn)行動(dòng)態(tài)調(diào)試。下面是一個(gè)簡單的例子。

        對應(yīng)每一個(gè)debug語句,我們也加入一個(gè)__debug_desc結(jié)構(gòu)到__debug數(shù)據(jù)段。

        提供給用戶一個(gè)函數(shù)用來打開或者關(guān)閉調(diào)試:test_debug()可以被設(shè)計(jì)成寫文件后者寫控制臺。

        在需要使用動(dòng)態(tài)調(diào)試的應(yīng)用程序里面加入如下代碼來初始化動(dòng)態(tài)調(diào)試。

        這樣這段程序在正常運(yùn)行是不會輸出“test dynamic debug”這行日志的,當(dāng)我們需要打開調(diào)試日志的時(shí)候,我們通過控制臺發(fā)送一個(gè)USR2信號到對應(yīng)的程序:

        Kill -USR2

        在接收到這個(gè)信號(Signal)以后,該程序中使用DBG()輸出的日志就會被打印出來。

        5 總結(jié)

        動(dòng)態(tài)調(diào)試技術(shù)已經(jīng)被廣泛應(yīng)用于Android內(nèi)核模塊開發(fā)中,越來越多的應(yīng)用程序和驅(qū)動(dòng)程序也在使用這樣的技術(shù),它以極少的資源消耗加速了程序開發(fā)調(diào)試的進(jìn)程。

        猜你喜歡
        內(nèi)核日志代碼
        萬物皆可IP的時(shí)代,我們當(dāng)夯實(shí)的IP內(nèi)核是什么?
        一名老黨員的工作日志
        強(qiáng)化『高新』內(nèi)核 打造農(nóng)業(yè)『硅谷』
        扶貧日志
        心聲歌刊(2020年4期)2020-09-07 06:37:14
        基于嵌入式Linux內(nèi)核的自恢復(fù)設(shè)計(jì)
        Linux內(nèi)核mmap保護(hù)機(jī)制研究
        創(chuàng)世代碼
        創(chuàng)世代碼
        創(chuàng)世代碼
        創(chuàng)世代碼
        国产精品厕所| 深夜放纵内射少妇| 免费1级做爰片1000部视频| 国产欧美VA欧美VA香蕉在| 亚洲AV无码一区二区三区精神| 水蜜桃网站视频在线观看| 永久天堂网av手机版| 久久久久99精品成人片试看| 人妻无码在线免费| 精品黑人一区二区三区久久hd| 国产av天堂亚洲国产av天堂| 波多野结衣中文字幕久久| 日韩亚洲欧美精品| 日韩极品在线观看视频| 亚洲sm另类一区二区三区| 亚洲黄色电影| 日韩精品一区二区亚洲av性色| 亚洲自拍偷拍色图综合| 鸭子tv国产在线永久播放| 成人激情四射网| 日本在线观看一区二区三区视频 | 国产乱国产乱老熟300部视频| 久久伊人影院| 少妇勾引视频网站在线观看| 寂寞人妻渴望被中出中文字幕| 亚洲国产精品福利片在线观看| 国产成人亚洲精品电影| 丝袜美腿亚洲综合在线播放 | 一区二区三区午夜视频在线| 青草内射中出高潮| 亚洲 国产 哟| 99久久久69精品一区二区三区| 少妇爆乳无码专区| 亚洲av国产av综合av| 天堂av在线一区二区| 国产成人精品一区二区20p| 亚洲熟少妇在线播放999| 91狼友在线观看免费完整版| 久久一区二区三区少妇人妻| 把女邻居弄到潮喷的性经历 | 在线一区二区三区免费视频观看|