<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 測試測量 > 嵌入式軟件測試的十大秘訣

嵌入式軟件測試的十大秘訣

——
作者: 時(shí)間:2007-02-27 來(lái)源: 收藏

在嵌入式軟件開(kāi)發(fā)過(guò)程中,一般來(lái)說(shuō),花在測試和花在編碼的時(shí)間比為3:1(實(shí)際上可能更多)。這個(gè)比例隨著(zhù)你的編程和測試水平的提高而不斷下降,但不論怎樣,軟件測試對一般人來(lái)講很重要。很多年前,一位開(kāi)發(fā)人員為了在對嵌入式有更深層次的理解,向Oracle詢(xún)問(wèn)了這樣的一個(gè)問(wèn)題:我怎么才能知道并懂得我的系統到底在干些什么呢? Oracle面對這個(gè)問(wèn)題有些吃驚,因為在當時(shí)沒(méi)有人這么問(wèn)過(guò),而同時(shí)代的嵌入式開(kāi)發(fā)人員問(wèn)的最多的大都圍繞“我怎么才能使程序跑的更快”、“什么編譯器最好”等膚淺的問(wèn)題。所以,面對這個(gè)不同尋常卻異乎成熟的問(wèn)題,Oracle感到欣喜并認真回復了他:你的問(wèn)題很有深度很成熟,因為只有不斷地去深入理解才有可能不斷地提高水平。并且Oracle為了鼓勵這位執著(zhù)的程序員,把10條關(guān)于嵌入式軟件開(kāi)發(fā)測試的秘訣告訴了他:


1.懂得使用工具
2.盡早發(fā)現內存問(wèn)題
3.深入理解代碼優(yōu)化
4.不要讓自己大海撈針
5.重現并隔離問(wèn)題
6.以退為進(jìn)
7.確定測試的完整性
8.提高代碼質(zhì)量意味著(zhù)節省時(shí)間
9.發(fā)現它,分析它,解決它
10.利用初學(xué)者的思維
 
這十條秘訣在業(yè)界廣為流傳,使很多人受益。本文圍繞這十條秘訣展開(kāi)論述。
 
1.懂得使用工具
  
  通常嵌入式系統對可靠性的要求比較高。嵌入式系統安全性的失效可能會(huì )導致災難性的后果,即使是非安全性系統,由于大批量生產(chǎn)也會(huì )導致嚴重的經(jīng)濟損失。這就要求對嵌入式系統,包括嵌入式軟件進(jìn)行嚴格的測試、確認和驗證。隨著(zhù)越來(lái)越多的領(lǐng)域使用軟件和微處理器控制各種嵌入式設備,對門(mén)益復雜的嵌入式軟件進(jìn)行快速有效的測試愈加顯得重要。


  就象修車(chē)需要工具一樣,好的程序員應該能夠熟練運用各種軟件工具。不同的工具,有不同的使用范圍,有不同的功能。使用這些工具,你可以看到你的系統在干些什么,它又占用什么資源,它到底和哪些外界的東西打交道。讓你郁悶好幾天的問(wèn)題可能通過(guò)某個(gè)工具就能輕松搞定,可惜你就是不知道。那么為什么那么多的人總是在折騰個(gè)半死之后才想到要用測試工具呢?原因很多,主要有兩個(gè)。一個(gè)是害怕,另一個(gè)是惰性。害怕是因為加入測試用具或測試模塊到代碼需要技巧同時(shí)有可能引入新的錯誤,所以他們總喜歡寄希望于通過(guò)不斷地修改重編譯代碼來(lái)消除bug,結果卻無(wú)濟于事。懶惰是因為他們習慣了使用printf之類(lèi)的簡(jiǎn)單測試手段。下面來(lái)介紹一些嵌入式常用的測試工具。


.源碼級調試器[Source-level Debugger]
這種調試器一般提供單步或多步調試、斷點(diǎn)設置、內存檢測、變量查看等功能,是嵌入式調試最根本有效的調試方法。比如VxWorks TornadoII提供的gdb就屬于這一種。


.簡(jiǎn)單實(shí)用的打印顯示工具[printf]
printf或其它類(lèi)似的打印顯示工具估計是最靈活最簡(jiǎn)單的調試工具。打印代碼執行過(guò)程中的各種變量可以讓你知道代碼執行的情況。但是,printf對正常的代碼執行干擾比較大(一般printf占用CPU比較長(cháng)的時(shí)間),需要慎重使用,最好設置打印開(kāi)關(guān)來(lái)控制打印。


.ICE或JTAG調試器[In-circuit Emulator]
ICE是用來(lái)仿真CPU核心的設備,它可以在不干擾運算器的正常運行情況下,實(shí)時(shí)的檢測CPU的內部工作情況。像桌面調試軟件所提供的:復雜的條件斷點(diǎn)、先進(jìn)的實(shí)時(shí)跟蹤、性能分析和端口分析這些功能,它也都能提供。ICE一般都有一個(gè)比較特殊的CPU,稱(chēng)為外合(bond-out)CPU。這是一種被打開(kāi)了封裝的CPU,并且通過(guò)特殊的連接,可以訪(fǎng)問(wèn)到CPU的內部信號,而這些信號,在CPU被封裝時(shí),是沒(méi)法“看到”的。當和工作站上強大的調試軟件聯(lián)合使用時(shí),ICE就能提供你所能找到的最全面的調試功能。但ICE同樣有一些缺點(diǎn):昂貴;不能全速工作;同樣,并不是所有的CPU都可以作為外合CPU的,從另一個(gè)角度說(shuō),這些外合CPU也不大可能及時(shí)的被新出的CPU所更換。JTAG(Joint Test Action Group)雖然它最初開(kāi)發(fā)出來(lái)是為了監測IC和電路連接,但是這種串行接口擴展了用途,包括對調試的支持。AD公司為Blackfin設計的Visual Dsp++就支持高速的JTAG調試。


.ROM監視器[ROM Monitor]
ROM監控器是一小程序,駐留在嵌入系統ROM中,通過(guò)串行的或網(wǎng)絡(luò )的連接和運行在工作站上的調試軟件通信。這是一種便宜的方式,當然也是最低端的技術(shù)。它除了要求一個(gè)通信端口和少量的內存空間外,不需要其它任何專(zhuān)門(mén)的硬件。并提供了如下功能:下載代碼、運行控制、斷點(diǎn)、單步步進(jìn)、以及觀(guān)察、修改寄存器和內存。因為ROM監控器是操作軟件的一部分,只有當你的應用程序運行時(shí),它才會(huì )工作。如果你想檢查CPU和應用程序的狀態(tài),你就必須停下應用程序,再次進(jìn)入ROM監控器。


.Data監視器[Data Monitor]
這種監視器在不停止CPU運行的情況下不僅可以顯示指定變量?jì)热?,還可以收集并以圖形形式顯示各個(gè)變量的變化過(guò)程。


.OS監視器[Operating System Monitor]
操作系統監視器可以顯示諸如任務(wù)切換、信號量收發(fā)、中斷等事件。一方面,這些監視器能夠為你呈現事件之間的關(guān)系和時(shí)間聯(lián)系;另一方面,還可以提供對信號量?jì)?yōu)先級反轉、死鎖和中斷延時(shí)等問(wèn)題的診斷。


.性能分析工具[Profiler]
可以用來(lái)測試CPU到底耗在那里。profiler工具可以讓你知道系統的瓶頸在那里、CPU的使用率以及需要優(yōu)化的地方。


.內存測試工具[Memory Teseter]
可以找到內存使用的問(wèn)題所在,比如內存泄露、內存碎片、內存崩潰等問(wèn)題。如果發(fā)現系統出現一些不可預知的或間歇性的問(wèn)題,就應該使用內存測試工具測測看。


.運行跟蹤器[Execution Tracer]
可以顯示CPU執行了哪些函數、誰(shuí)在調用、參數是什么、何時(shí)調用等情況。這種工具主要用于測試代碼邏輯,可以在大量的事件中發(fā)現異常的那些。


.覆蓋工具[Coverage Tester]
主要顯示CPU具體執行了那些代碼,并讓你知道那些代碼分支沒(méi)有被執行到。這樣有助于提高代碼質(zhì)量并消除無(wú)用代碼。


.GUI測試工具[GUI Tester]
很多嵌入式應用帶有某種形式的圖形用戶(hù)界面進(jìn)行交互,有些系統性能測試足根掘用戶(hù)輸入響應時(shí)間進(jìn)行的。GUI測試工具可以作為腳本工具有開(kāi)發(fā)環(huán)境中運行測試用例,其功能包括對操作的記錄和回放、抓取屏幕顯示供以后分析和比較、設置和管理測試過(guò)程(Rational公司的robot和Mercury的Loadrunner工具是杰出的代表)。很多嵌入式設備沒(méi)有GUI,但常??梢詫η度胧皆O備進(jìn)行插裝來(lái)運行GUI測試腳本,雖然這種方式可能要求對被測代碼進(jìn)行更改,但是節省了功能測試和回歸測試的時(shí)間。


.自制工具[Home-made tester]
在嵌入式應用中,有時(shí)候為了特定的目的,需要自行編寫(xiě)一些工具來(lái)達到某種測試目的。本人曾經(jīng)編寫(xiě)的視頻流錄顯工具在測試視頻會(huì )議數據流向和變化上幫了大忙,幫公司找到了幾個(gè)隱藏很深的bug。
 
2.盡早發(fā)現內存問(wèn)題
  內存問(wèn)題危害很大,不容易排查,主要有三種類(lèi)型:內存泄露、內存碎片和內存崩潰。對于內存問(wèn)題態(tài)度必須要明確,那就是早發(fā)現早“治療”。在軟件設計中,內存泄露的“名氣”最大,主要由于不斷分配的內存無(wú)法及時(shí)地被釋放,久而久之,系統的內存耗盡。即使細心的編程老手有時(shí)后也會(huì )遭遇內存泄露問(wèn)題。有測試過(guò)內存泄露的朋友估計都有深刻地體驗,那就是內存泄露問(wèn)題一般隱藏很深,很難通過(guò)代碼閱讀來(lái)發(fā)現。有些內存泄露甚至可能出現在庫當中。有可能這本身是庫中的bug,也有可能是因為程序員沒(méi)有正確理解它們的接口說(shuō)明文檔造成錯用。


  在很多時(shí)候,大多數的內存泄露問(wèn)題無(wú)法探測,但可能表現為隨機的故障。程序員們往往會(huì )把這種現象怪罪于硬件問(wèn)題。如果用戶(hù)對系統穩定性不是很高,那么重啟系統問(wèn)題也不大;但,如果用戶(hù)對系統穩定很高,那么這種故障就有可能使用戶(hù)對產(chǎn)品失去信心,同時(shí)也意味著(zhù)你的項目是個(gè)失敗的項目。由于內存泄露危害巨大,現在已經(jīng)有許多工具來(lái)解決這個(gè)問(wèn)題。這些工具通過(guò)查找沒(méi)有引用或重復使用的代碼塊、垃圾內存收集、庫跟蹤等技術(shù)來(lái)發(fā)現內存泄露的問(wèn)題。每個(gè)工具都有利有弊,不過(guò)總的來(lái)說(shuō),用要比不用好??傊?,負責的開(kāi)發(fā)人員應該去測試內存泄露的問(wèn)題,做到防患于未然。


  內存碎片比內存泄露隱藏還要深。隨著(zhù)內存的不斷分配并釋放,大塊內存不斷分解為小塊內存,從而形成碎片,久而久之,當需要申請大塊內存是,有可能就會(huì )失敗。如果系統內存夠大,那么堅持的時(shí)間會(huì )長(cháng)一些,但最終還是逃不出分配失敗的厄運。在使用動(dòng)態(tài)分配的系統中,內存碎片經(jīng)常發(fā)生。目前,解決這個(gè)問(wèn)題最效的方法就是使用工具通過(guò)顯示系統中內存的使用情況來(lái)發(fā)現誰(shuí)是導致內存碎片的罪魁禍首,然后改進(jìn)相應的部分。


  由于動(dòng)態(tài)內存管理的種種問(wèn)題,在嵌入式應用中,很多公司干脆就禁用malloc/free的以絕后患。


  內存崩潰是內存使用最嚴重的結果,主要原因有數組訪(fǎng)問(wèn)越界、寫(xiě)已經(jīng)釋放的內存、指針計算錯誤、訪(fǎng)問(wèn)堆棧地址越界等等。這種內存崩潰造成系統故障是隨機的,而且很難查找,目前提供用于排查的工具也很少。


  總之,如果要使用內存管理單元的話(huà),必須要小心,并嚴格遵守它們的使用規則,比如誰(shuí)分配誰(shuí)釋放。
 
3.深入理解代碼優(yōu)化
  講到系統穩定性,人們更多地會(huì )想到實(shí)時(shí)性和速度,因為代碼效率對嵌入式系統來(lái)說(shuō)太重要了。知道怎么優(yōu)化代碼是每個(gè)嵌入式軟件開(kāi)發(fā)人員必須具備的技能。就象女孩子減肥一樣,起碼知道她哪個(gè)地方最需要減,才能去購買(mǎi)減肥藥或器材來(lái)減掉它??梢?jiàn),代碼優(yōu)化的前提是找到真正需要優(yōu)化的地方,然后對癥下藥,優(yōu)化相應部分的代碼。前面提到的profile(性能分析工具,一些功能齊全IDE都提供這種內置的工具)能夠記錄各種情況比如各個(gè)任務(wù)的CPU占用率、各個(gè)任務(wù)的優(yōu)先級是否分配妥當、某個(gè)數據被拷貝了多少次、訪(fǎng)問(wèn)磁盤(pán)多少次、是否調用了網(wǎng)絡(luò )收發(fā)的程序、測試代碼是否已經(jīng)關(guān)閉等等。


  但是,profile工具在分析實(shí)時(shí)系統性能方面還是有不夠的地方。一方面,人們使用profile工具往往是在系統出現問(wèn)題即CPU耗盡之后,而profile工具本身對CPU占用較大,所以profile對這種情況很可能不起作用。根據Heisenberg效應,任何測試手段或多或少都會(huì )改變系統運行,這個(gè)對profiler同樣適用!


  總之,提高運行效率的前提是你必須要知道CPU到底干了些什么干的怎么樣。
 
4.不要讓自己大海撈針


  大海撈針只是對調試的一種生動(dòng)比喻。


  經(jīng)常聽(tīng)到組里有人對自己正在調試的代碼說(shuō)shit!可以理解,因為代碼不是他寫(xiě)的,他有足夠的理由去shit bug百出的代碼,只要他自己不要寫(xiě)出這種代碼,否則有一天同組的其它人可能同樣會(huì )shit他寫(xiě)的代碼。為何會(huì )有大海撈針呢?肯定是有人把針掉到海里咯;那針為何會(huì )掉在海里呢?肯定是有人不小心或草率唄。所以當你在抱怨針那么難找的時(shí)候,你是否想過(guò)是你自己草率地丟掉的。同樣,當你調試個(gè)半死的時(shí)候,你是否想過(guò)你要好好反省一下當初為了尋求捷徑可能沒(méi)有嚴格地遵守好的編碼設計規范、沒(méi)有檢測一些假設條件或算法的正確性、沒(méi)有將一些可能存在問(wèn)題的代碼打上記號呢?關(guān)于如何寫(xiě)高質(zhì)量請參考林銳的《高質(zhì)量c++/c編程指南》或《關(guān)于C的0x8本“經(jīng)書(shū)”》(http://blog.sina.com.cn/u/4a317b79010004mc)。
  如果你確實(shí)已經(jīng)把針掉在海里是,為了防止在找到之前刺到自己,你必須要做一些防范工作,比如戴上安全手套。同樣,為了盡能地暴露和捕捉問(wèn)題根源,我們可以設計比較全面的錯誤跟蹤代碼。怎么來(lái)做呢?盡可能對每個(gè)函數調用失敗作出處理,盡可能檢測每個(gè)參數輸入輸出的有效性包括指針以及檢測是否過(guò)多或過(guò)少地調用某個(gè)過(guò)程。錯誤跟蹤能夠讓你知道你大概把針掉在哪個(gè)位置。
 
5.重現并隔離問(wèn)題
  如果你不是把針掉在大海了,而是掉在草堆里,那要好辦寫(xiě)。因為至少我們可以把草堆分成很多塊,一塊一塊的找。對于模塊獨立的大型項目,使用隔離方法往往是對付那些隱藏極深bug的最后方法。如果問(wèn)題的出現是間歇性的,我們有必要設法去重現它并記錄使其重現的整個(gè)過(guò)程以備在下一次可以利用這些條件去重現問(wèn)題。如果你確信可以使用記錄的那些條件去重現問(wèn)題,那么我們就可以著(zhù)手去隔離問(wèn)題。怎么隔離呢?我們可以用#ifdef把一些可能和問(wèn)題無(wú)關(guān)的代碼關(guān)閉,把系統最小化到仍能夠重現問(wèn)題的地步。如果還是無(wú)法定位問(wèn)題所在,那么有必要打開(kāi)“工具箱”了??梢栽囍?zhù)用ICE或數據監視器去查看某個(gè)可疑變量的變化;可以使用跟蹤工具獲得函數調用的情況包括參數的傳遞;檢查內存是否崩潰以及堆棧溢出的問(wèn)題。
 
6.以退為進(jìn)
  獵人為了不使自己在森林里迷路,他常常會(huì )在樹(shù)木上流下一些標記,以備自己將來(lái)有一天迷路時(shí)可以根據這些標記找到出路。對過(guò)去代碼的修改進(jìn)行跟蹤記錄對將來(lái)出現問(wèn)題之后的調試很有幫助。假如有一天,你最近一次修改的程序跑了很久之后忽然死掉了,那么你這時(shí)的第一反映就是我到底改動(dòng)了些什么呢,因為上次修改之前是好的。那么如何檢測這次相對于上次的修改呢?沒(méi)錯,代碼控制系統SCS或稱(chēng)版本控制系統VCS(Concurrent Version Control,CVS是VCS的演化版本)。將上個(gè)版本check in下來(lái)后和當前測試版本比較。比較的工具可以是SCS/VCS/CVS自帶的diff工具或其它功能更強的比較工具,比如BeyondCompare和ExamDiff。通過(guò)比較,記錄所有改動(dòng)的代碼,分析所有可能導致問(wèn)題的可疑代碼。
 
7.確定測試的完整性
  你怎么知道你的測試有多全面呢?覆蓋測試(coverage testing)可以回答這個(gè)問(wèn)題。覆蓋測試工具可以告訴你CPU到底執行了那些代碼。好的覆蓋工具通??梢愿嬖V你大概20%到40%代碼沒(méi)有問(wèn)題,而其余的可能存在bug。覆蓋工具有不同的測試級別,用戶(hù)可以根據自己的需要選擇某個(gè)級別。即使你很確信你的單元測試已經(jīng)很全面并且沒(méi)有dead code,覆蓋工具還是可以為你指出一些潛在的問(wèn)題,看下面的代碼:
if (i >= 0 && (almostAlwaysZero == 0 || (last = i)))
如果almostAlwaysZero為非0,那么last=i賦值語(yǔ)句就被跳過(guò),這可能不是你所期望的。這種問(wèn)題通過(guò)覆蓋工具的條件測試功能可以輕松的被發(fā)現。
  總之,覆蓋測試對于提高代碼質(zhì)量很有幫助。
 
 
8.提高代碼質(zhì)量意味著(zhù)節省時(shí)間
  有研究表明軟件開(kāi)發(fā)的時(shí)間超過(guò)80%被用在下面幾個(gè)方面:
.調試自己的代碼(單元測試)
.調試自己和其他相關(guān)的代碼(模塊間測試)
.調試整個(gè)系統(系統測試)
更糟糕的是你可能需要花費10-200倍的時(shí)間來(lái)找一個(gè)bug,而這個(gè)bug在開(kāi)始的時(shí)候可能很容易就能找到。一個(gè)小bug可能讓你付出巨大的代價(jià),即使這個(gè)bug對整個(gè)系統的性能沒(méi)有太大的影響,但很可能會(huì )影響讓那些你可以看得到的部分。所以我們必須要養成良好的編碼和測試手段以求更高的代碼質(zhì)量,以便縮短調試的代碼?!?BR> 
9.發(fā)現它,分析它,解決它
  這世界沒(méi)有萬(wàn)能的膏藥。profile再強大也有力不從心的時(shí)候;內存監視器再好,也有無(wú)法發(fā)現的時(shí)候;覆蓋工具再好用,也有不能覆蓋的地方。一些隱藏很深的問(wèn)題即使用盡所有工具也有可能無(wú)法查到其根源,這時(shí)我們能做的就是通過(guò)這些問(wèn)題所表現出來(lái)的外在現象或一些數據輸出來(lái)發(fā)現其中的規律或異常。一旦發(fā)現任何異常,一定要深入地理解并回溯其根源,直到解決為止。
 
10.利用初學(xué)者的思維
  有人這樣說(shuō)過(guò):“有些事情在初學(xué)者的腦子里可能有各種各樣的情況,可在專(zhuān)家的頭腦里可能就很單一”。有時(shí)候,有些簡(jiǎn)單的問(wèn)題會(huì )被想的很復雜,有些簡(jiǎn)單的系統別設計的很復雜,就是由于你的“專(zhuān)家思維”。當你被問(wèn)題難住時(shí),關(guān)掉電腦,出去走走,把你的問(wèn)題和你的朋友甚至你的小狗說(shuō)說(shuō),或許他們可以給你意想不到的啟發(fā)。
 
總結:嵌入式調試也是一門(mén)藝術(shù)。就想其它的藝術(shù)一樣,如果你想取得成功,你必須具備智慧、經(jīng)驗并懂得使用工具。只要我們能夠很好地領(lǐng)悟Oracle這十條秘訣,我相信我們在嵌入式測試方面就能夠取得成功。



評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>