关闭

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

发表于:2013-6-05 10:22

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ce123    来源:51Testing软件测试网采编

  ● 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怎么办呢,看函数,它是从后面往前拷贝,这样就能正确拷贝数据了。根据上面的分析,理解下面的代码应该是一件很容易的事情。

551 #ifndef __HAVE_ARCH_MEMCPY
552 /**
553  * memcpy - Copy one area of memory to another
554  * @dest: Where to copy to
555  * @src: Where to copy from
556  * @count: The size of the area.
557  *
558  * You should not use this function to access IO space, use memcpy_toio()
559  * or memcpy_fromio() instead.
560  */
561 void *memcpy(void *dest, const void *src, size_t count)
562 {
563         char *tmp = dest;
564         const char *s = src;
565
566         while (count--)
567                 *tmp++ = *s++;
568         return dest;
569 }
570 EXPORT_SYMBOL(memcpy);
571 #endif
572
573 #ifndef __HAVE_ARCH_MEMMOVE
574 /**
575  * memmove - Copy one area of memory to another
576  * @dest: Where to copy to
577  * @src: Where to copy from
578  * @count: The size of the area.
579  *
580  * Unlike memcpy(), memmove() copes with overlapping areas.
581  */
582 void *memmove(void *dest, const void *src, size_t count)
583 {
584         char *tmp;
585         const char *s;
586
587         if (dest <= src) {
588                 tmp = dest;
589                 s = src;
590                 while (count--)
591                         *tmp++ = *s++;
592         } else {
593                 tmp = dest;
594                 tmp += count;
595                 s = src;
596                 s += count;
597                 while (count--)
598                         *--tmp = *--s;
599         }
600         return dest;
601 }
602 EXPORT_SYMBOL(memmove);
603 #endif

《2023软件测试行业现状调查报告》独家发布~

精彩评论

  • yun@123
    2013-6-06 10:30:38

    恩,这样啊,第一次见到memmove这个函数,以前写memcopy函数的时候就是按照memmove函数这么写的,今天才发现它们还有这种区别,当时还挺不理解为什么分两种情况来拷贝呢,现在总算明白了,谢谢楼主的文章。

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号