linux內(nèi)核中memcpy和memmove函數(shù)的區(qū)別和實現(xiàn)
CPU architecture:ARM
本文引用地址:http://m.butianyuan.cn/article/201611/320009.htmAuthor:ce123(http://blog.csdn.net/ce123)
- memcpy是把src指向的對象中的size個字符拷貝到dest所指向的對象中,返回指向結(jié)果對象的指針.
- memmove也是把src指向的對象中的size個字符拷貝到dest所指向的對象中,返回指向結(jié)果對象的指針,但這兩個函數(shù)在處理內(nèi)存區(qū)域重疊的方式不同.
內(nèi)存重疊問題是指目的地址的內(nèi)存空間的首地址,包含在源內(nèi)存空間中,這兩段內(nèi)存空間有了交集,因而在使用memcpy進行內(nèi)存復制操作時,這段重疊的內(nèi)存空間會被破壞.這種情況在應(yīng)用程序級代碼中一般不會出現(xiàn)的,而在驅(qū)動或內(nèi)核級代碼中要十分小心,盡量使用memmove函數(shù).
memcpy對內(nèi)存空間有要求的,dest和src所指向的內(nèi)存空間不能重疊,否則復制的數(shù)據(jù)是錯誤的.下面具體講解一下這個錯誤是如何產(chǎn)生的.
如果內(nèi)存空間布局入下圖所示:
src所指向的內(nèi)存空間后面部分數(shù)據(jù)被新拷貝的數(shù)據(jù)給覆蓋了(也就是dest<=src+size).所以拷貝到最后,原來的數(shù)據(jù)肯定不是原來的數(shù)據(jù),拷貝的數(shù)據(jù)也不是想要的數(shù)據(jù),使用memcpy函數(shù)可以得到錯誤的結(jié)果.
再者,如果內(nèi)存空間布局入下圖所示:
雖然原來的數(shù)據(jù)不再是原來的數(shù)據(jù)(dest+size>=src),但拷貝的數(shù)據(jù)是原來的數(shù)據(jù),使用memcpy函數(shù)可以得到正確的結(jié)果.因此,在使用memcpy這個函數(shù)之前,還需要做一個判斷,如果dest<=src你才能使用這個函數(shù)不過完全沒有必要,你直接使用memmove函數(shù)就可以了.memmove在拷貝之前就做了一個判斷,如果dest <= src,就按照memcpy的思路拷貝,如果dest>src怎么辦呢,看函數(shù),它是從后面往前拷貝,這樣就能正確拷貝數(shù)據(jù)了.根據(jù)上面的分析,理解下面的代碼應(yīng)該是一件很容易的事情.
- 551#ifndef__HAVE_ARCH_MEMCPY
- 552/**
- 553*memcpy-Copyoneareaofmemorytoanother
- 554*@dest:Wheretocopyto
- 555*@src:Wheretocopyfrom
- 556*@count:Thesizeofthearea.
- 557*
- 558*YoushouldnotusethisfunctiontoaccessIOspace,usememcpy_toio()
- 559*ormemcpy_fromio()instead.
- 560*/
- 561void*memcpy(void*dest,constvoid*src,size_tcount)
- 562{
- 563char*tmp=dest;
- 564constchar*s=src;
- 565
- 566while(count--)
- 567*tmp++=*s++;
- 568returndest;
- 569}
- 570EXPORT_SYMBOL(memcpy);
- 571#endif
- 572
- 573#ifndef__HAVE_ARCH_MEMMOVE
- 574/**
- 575*memmove-Copyoneareaofmemorytoanother
- 576*@dest:Wheretocopyto
- 577*@src:Wheretocopyfrom
- 578*@count:Thesizeofthearea.
- 579*
- 580*Unlikememcpy(),memmove()copeswithoverlappingareas.
- 581*/
- 582void*memmove(void*dest,constvoid*src,size_tcount)
- 583{
- 584char*tmp;
- 585constchar*s;
- 586
- 587if(dest<=src){
- 588tmp=dest;
- 589s=src;
- 590while(count--)
- 591*tmp++=*s++;
- 592}else{
- 593tmp=dest;
- 594tmp+=count;
- 595s=src;
- 596s+=count;
- 597while(count--)
- 598*--tmp=*--s;
- 599}
- 600returndest;
- 601}
- 602EXPORT_SYMBOL(memmove);
- 603#endif
評論