在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            linux內(nèi)核中的IS_ERR

            作者: 時(shí)間:2016-11-22 來(lái)源:網(wǎng)絡(luò) 收藏
            在看內(nèi)核源碼的時(shí)候,經(jīng)常會(huì)遇到IS_ERR,比如在linux/arch/arm/kernel/sys_arm.c中

            本文引用地址:http://www.biyoush.com/article/201611/319992.htm
            [plain]view plaincopy
            print?
            1. asmlinkageintsys_execve(char__user*filenamei,char__user*__user*argv,
            2. char__user*__user*envp,structpt_regs*regs)
            3. {
            4. interror;
            5. char*filename;
            6. filename=getname(filenamei);
            7. error=PTR_ERR(filename);
            8. if(IS_ERR(filename))
            9. gotoout;
            10. error=do_execve(filename,argv,envp,regs);
            11. putname(filename);
            12. out:
            13. returnerror;
            14. }
            IS_ERR宏定義在include/linux/err.h,如下所示:

            [plain]view plaincopy
            print?
            1. #ifndef_LINUX_ERR_H
            2. #define_LINUX_ERR_H
            3. #include
            4. #include
            5. /*
            6. *Kernelpointershaveredundantinformation,sowecanusea
            7. *schemewherewecanreturneitheranerrorcodeoradentry
            8. *pointerwiththesamereturnvalue.
            9. *
            10. *Thisshouldbeaper-architecturething,toallowdifferent
            11. *errorandpointerdecisions.
            12. */
            13. #defineIS_ERR_VALUE(x)unlikely((x)>(unsignedlong)-1000L)
            14. staticinlinevoid*ERR_PTR(longerror)
            15. {
            16. return(void*)error;
            17. }
            18. staticinlinelongPTR_ERR(constvoid*ptr)
            19. {
            20. return(long)ptr;
            21. }
            22. staticinlinelongIS_ERR(constvoid*ptr)
            23. {
            24. returnIS_ERR_VALUE((unsignedlong)ptr);
            25. }
            26. #endif/*_LINUX_ERR_H*/
            下面我們就來(lái)具體分析一下這段代碼,看看內(nèi)核中的巧妙設(shè)計(jì)思路。

            要想明白IS_ERR(),首先理解要內(nèi)核空間。所有的驅(qū)動(dòng)程序都是運(yùn)行在內(nèi)核空間,內(nèi)核空間雖然很大,但總是有限的,而在這有限的空間中,其最后一個(gè)page是專(zhuān)門(mén)保留的,也就是說(shuō)一般人不可能用到內(nèi)核空間最后一個(gè)page的指針。換句話(huà)說(shuō),你在寫(xiě)設(shè)備驅(qū)動(dòng)程序的過(guò)程中,涉及到的任何一個(gè)指針,必然有三種情況:

            1. 有效指針;
            2. NULL,空指針;
            3. 錯(cuò)誤指針,或者說(shuō)無(wú)效指針。

            而所謂的錯(cuò)誤指針就是指其已經(jīng)到達(dá)了最后一個(gè)page,即內(nèi)核用最后一頁(yè)捕捉錯(cuò)誤。比如對(duì)于32bit的系統(tǒng)來(lái)說(shuō),內(nèi)核空間最高地址0xffffffff,那么最后一個(gè)page就是指的0xfffff000~0xffffffff(假設(shè)4k一個(gè)page),這段地址是被保留的。內(nèi)核空間為什么留出最后一個(gè)page?我們知道一個(gè)page可能是4k,也可能是更多,比如8k,但至少它也是4k,所以留出一個(gè)page出來(lái)就可以讓我們把內(nèi)核空間的指針來(lái)記錄錯(cuò)誤了。內(nèi)核返回的指針一般是指向頁(yè)面的邊界(4k邊界),即ptr & 0xfff == 0。如果你發(fā)現(xiàn)你的一個(gè)指針指向這個(gè)范圍中的某個(gè)地址,那么你的代碼肯定出錯(cuò)了。IS_ERR()就是判斷指針是否有錯(cuò),如果指針并不是指向最后一個(gè)page,那么沒(méi)有問(wèn)題;如果指針指向了最后一個(gè)page,那么說(shuō)明實(shí)際上這不是一個(gè)有效的指針,這個(gè)指針里保存的實(shí)際上是一種錯(cuò)誤代碼。而通常很常用的方法就是先用IS_ERR()來(lái)判斷是否是錯(cuò)誤,然后如果是,那么就調(diào)用PTR_ERR()來(lái)返回這個(gè)錯(cuò)誤代碼。因此,判斷一個(gè)指針是不是有效的,可用如下的方式:

            #define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L)

            (unsigned long)-1000L 應(yīng)該為 (unsigned long)-0x1000L!(因?yàn)?-0x1000 才是 0xFFFFF000),這應(yīng)該是內(nèi)核的一個(gè)bug吧!在2.6.30.4的內(nèi)核中是這樣定義的:

            [plain]view plaincopy
            print?
            1. #defineMAX_ERRNO4095
            2. #defineIS_ERR_VALUE(x)unlikely((x)>=(unsignedlong)-MAX_ERRNO)

            即判斷是不是在(0xfffff000,0xffffffff)之間,因此,可以用IS_ERR()來(lái)判斷內(nèi)核函數(shù)的返回值是不是一個(gè)有效的指針。注意這里用unlikely()的用意!

            至于PTR_ERR(), ERR_PTR(),只是強(qiáng)制轉(zhuǎn)換以下而已?,F(xiàn)在應(yīng)該知道為什么我寫(xiě)返回錯(cuò)誤碼的時(shí)候也加個(gè)負(fù)號(hào)如 -ENOSYS這樣子了。而PTR_ERR()只是返回錯(cuò)誤代碼,也就是提供一個(gè)信息給調(diào)用者,如果你只需要知道是否出錯(cuò),而不在乎因?yàn)槭裁炊鲥e(cuò),那你當(dāng)然不用調(diào)用PTR_ERR()了。

            而我們的錯(cuò)誤碼的值在內(nèi)存中定義都是這樣的(asm-generic/errno-base.h):

            [plain]view plaincopy
            print?
            1. ......
            2. #defineEPERM1/*Operationnotpermitted*/
            3. #defineENOENT2/*Nosuchfileordirectory*/
            4. #defineESRCH3/*Nosuchprocess*/
            5. #defineEINTR4/*Interruptedsystemcall*/
            6. #defineEIO5/*I/Oerror*/
            7. #defineENXIO6/*Nosuchdeviceoraddress*/
            8. #defineE2BIG7/*Argumentlisttoolong*/
            9. #defineENOEXEC8/*Execformaterror*/
            10. #defineEBADF9/*Badfilenumber*/
            11. #defineECHILD10/*Nochildprocesses*/
            12. #defineEAGAIN11/*Tryagain*/
            13. #defineENOMEM12/*Outofmemory*/
            14. #defineEACCES13/*Permissiondenied*/
            15. #defineEFAULT14/*Badaddress*/
            16. #defineENOTBLK15/*Blockdevicerequired*/
            17. #defineEBUSY16/*Deviceorresourcebusy*/
            18. #defineEEXIST17/*Fileexists*/
            19. #defineEXDEV18/*Cross-devicelink*/
            20. #defineENODEV19/*Nosuchdevice*/
            21. #defineENOTDIR20/*Notadirectory*/
            22. #defineEISDIR21/*Isadirectory*/
            23. #defineEINVAL22/*Invalidargument*/
            24. #defineENFILE23/*Filetableoverflow*/
            25. #defineEMFILE24/*Toomanyopenfiles*/
            26. #defineENOTTY25/*Notatypewriter*/
            27. #defineETXTBSY26/*Textfilebusy*/
            28. #defineEFBIG27/*Filetoolarge*/
            29. #defineENOSPC28/*Nospaceleftondevice*/
            30. #defineESPIPE29/*Illegalseek*/
            31. #defineEROFS30/*Read-onlyfilesystem*/
            32. #defineEMLINK31/*Toomanylinks*/
            33. #defineEPIPE32/*Brokenpipe*/
            34. #defineEDOM33/*Mathargumentoutofdomainoffunc*/
            35. #defineERANGE34/*Mathresultnotrepresentable*/
            36. ........
            如果指針指向了最后一個(gè)page,那么說(shuō)明實(shí)際上這不是一個(gè)有效的指針。這個(gè)指針里保存的實(shí)際上是一種錯(cuò)誤代碼。而通常很常用的方法就是先用IS_ERR()來(lái)判斷是否是錯(cuò)誤,然后如果是,那么就調(diào)用PTR_ERR()來(lái)返回這個(gè)錯(cuò)誤代碼。


            關(guān)鍵詞: linux內(nèi)核IS_ER

            評(píng)論


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

            關(guān)閉