×
单片机 > 单片机程序设计 > 详情

linux内核中memcpy和memmove函数的区别和实现

发布时间:2020-08-31 发布时间:
|
Kernel version:2.6.32

CPU architecture:ARM

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 plain copy
 
 print?
  1. 551 #ifndef __HAVE_ARCH_MEMCPY  
  2. 552 /**  
  3. 553  * memcpy - Copy one area of memory to another  
  4. 554  * @dest: Where to copy to  
  5. 555  * @src: Where to copy from  
  6. 556  * @count: The size of the area.  
  7. 557  *  
  8. 558  * You should not use this function to access IO space, use memcpy_toio()  
  9. 559  * or memcpy_fromio() instead.  
  10. 560  */  
  11. 561 void *memcpy(void *dest, const void *src, size_t count)  
  12. 562 {  
  13. 563         char *tmp = dest;  
  14. 564         const char *s = src;  
  15. 565   
  16. 566         while (count--)  
  17. 567                 *tmp++ = *s++;  
  18. 568         return dest;  
  19. 569 }  
  20. 570 EXPORT_SYMBOL(memcpy);  
  21. 571 #endif  
  22. 572   
  23. 573 #ifndef __HAVE_ARCH_MEMMOVE  
  24. 574 /**  
  25. 575  * memmove - Copy one area of memory to another  
  26. 576  * @dest: Where to copy to  
  27. 577  * @src: Where to copy from  
  28. 578  * @count: The size of the area.  
  29. 579  *  
  30. 580  * Unlike memcpy(), memmove() copes with overlapping areas.  
  31. 581  */  
  32. 582 void *memmove(void *dest, const void *src, size_t count)  
  33. 583 {  
  34. 584         char *tmp;  
  35. 585         const char *s;  
  36. 586   
  37. 587         if (dest <= src) {  
  38. 588                 tmp = dest;  
  39. 589                 s = src;  
  40. 590                 while (count--)  
  41. 591                         *tmp++ = *s++;  
  42. 592         } else {  
  43. 593                 tmp = dest;  
  44. 594                 tmp += count;  
  45. 595                 s = src;  
  46. 596                 s += count;  
  47. 597                 while (count--)  
  48. 598                         *--tmp = *--s;  
  49. 599         }  
  50. 600         return dest;  
  51. 601 }  
  52. 602 EXPORT_SYMBOL(memmove);  
  53. 603 #endif  


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
8051单片机的函数发生器的设计