新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > linux內核中memcpy和memmove函數的區別和實現

        linux內核中memcpy和memmove函數的區別和實現

        作者: 時間:2016-11-22 來源:網絡 收藏
        Kernel version:2.6.32

        CPU architecture:ARM

        本文引用地址:http://www.104case.com/article/201611/320009.htm

        Author:ce123(http://blog.csdn.net/ce123)

        • memcpy是把src指向的對象中的size個字符拷貝到dest所指向的對象中,返回指向結果對象的指針.
        • memmove也是把src指向的對象中的size個字符拷貝到dest所指向的對象中,返回指向結果對象的指針,但這兩個函數在處理內存區域重疊的方式不同.
        注意memmove這個函數名稱中有"move"這個單詞,而實際上src處的數據仍然還在,并沒有真的被"移動"了!這個函數名稱有它的歷史原因,是因為有了memcpy函數后,發現這個函數有問題,又發明了另一個沒有問題的memcpy函數,但為了爆出兼容性依然保留了memcpy函數,而將新版本的memcpy函數改名為memmove函數.

        內存重疊問題是指目的地址的內存空間的首地址,包含在源內存空間中,這兩段內存空間有了交集,因而在使用memcpy進行內存復制操作時,這段重疊的內存空間會被破壞.這種情況在應用程序級代碼中一般不會出現的,而在驅動或內核級代碼中要十分小心,盡量使用memmove函數.

        memcpy對內存空間有要求的,dest和src所指向的內存空間不能重疊,否則復制的數據是錯誤的.下面具體講解一下這個錯誤是如何產生的.

        如果內存空間布局入下圖所示:

        src所指向的內存空間后面部分數據被新拷貝的數據給覆蓋了(也就是dest<=src+size).所以拷貝到最后,原來的數據肯定不是原來的數據,拷貝的數據也不是想要的數據,使用memcpy函數可以得到錯誤的結果.

        再者,如果內存空間布局入下圖所示:

        雖然原來的數據不再是原來的數據(dest+size>=src),但拷貝的數據是原來的數據,使用memcpy函數可以得到正確的結果.因此,在使用memcpy這個函數之前,還需要做一個判斷,如果dest<=src你才能使用這個函數不過完全沒有必要,你直接使用memmove函數就可以了.memmove在拷貝之前就做了一個判斷,如果dest <= src,就按照memcpy的思路拷貝,如果dest>src怎么辦呢,看函數,它是從后面往前拷貝,這樣就能正確拷貝數據了.根據上面的分析,理解下面的代碼應該是一件很容易的事情.

        [plain]view plaincopy
        print?
        1. 551#ifndef__HAVE_ARCH_MEMCPY
        2. 552/**
        3. 553*memcpy-Copyoneareaofmemorytoanother
        4. 554*@dest:Wheretocopyto
        5. 555*@src:Wheretocopyfrom
        6. 556*@count:Thesizeofthearea.
        7. 557*
        8. 558*YoushouldnotusethisfunctiontoaccessIOspace,usememcpy_toio()
        9. 559*ormemcpy_fromio()instead.
        10. 560*/
        11. 561void*memcpy(void*dest,constvoid*src,size_tcount)
        12. 562{
        13. 563char*tmp=dest;
        14. 564constchar*s=src;
        15. 565
        16. 566while(count--)
        17. 567*tmp++=*s++;
        18. 568returndest;
        19. 569}
        20. 570EXPORT_SYMBOL(memcpy);
        21. 571#endif
        22. 572
        23. 573#ifndef__HAVE_ARCH_MEMMOVE
        24. 574/**
        25. 575*memmove-Copyoneareaofmemorytoanother
        26. 576*@dest:Wheretocopyto
        27. 577*@src:Wheretocopyfrom
        28. 578*@count:Thesizeofthearea.
        29. 579*
        30. 580*Unlikememcpy(),memmove()copeswithoverlappingareas.
        31. 581*/
        32. 582void*memmove(void*dest,constvoid*src,size_tcount)
        33. 583{
        34. 584char*tmp;
        35. 585constchar*s;
        36. 586
        37. 587if(dest<=src){
        38. 588tmp=dest;
        39. 589s=src;
        40. 590while(count--)
        41. 591*tmp++=*s++;
        42. 592}else{
        43. 593tmp=dest;
        44. 594tmp+=count;
        45. 595s=src;
        46. 596s+=count;
        47. 597while(count--)
        48. 598*--tmp=*--s;
        49. 599}
        50. 600returndest;
        51. 601}
        52. 602EXPORT_SYMBOL(memmove);
        53. 603#endif



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 水富县| 泰顺县| 平阳县| 遂宁市| 治县。| 鞍山市| 河源市| 历史| 大宁县| 阳朔县| 科技| 高雄市| 怀柔区| 临泽县| 武安市| 萨嘎县| 荃湾区| 青川县| 漠河县| 卢湾区| 德清县| 疏勒县| 台南县| 凭祥市| 定襄县| 隆安县| 苏尼特右旗| 祁门县| 吉木乃县| 光泽县| 花莲县| 响水县| 噶尔县| 历史| 中牟县| 孝昌县| 乐山市| 钦州市| 扶风县| 拜城县| 嘉义市|