Linux内核中memcpy和memmove函数的区别和实现
来源:互联网 发布:无间道3五个卧底 知乎 编辑:程序博客网 时间:2024/06/06 20:58
● 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_MEMCPY552 /**
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
- linux内核中memcpy和memmove函数的区别和实现
- linux内核中memcpy和memmove函数的区别和实现
- linux内核中memcpy和memmove函数的区别和实现
- Linux内核中memcpy和memmove函数的区别和实现
- linux内核中memcpy和memmove函数的区别和实现
- memcpy和memmove函数的区别和实现
- memcpy函数和memmove函数的模拟实现与区别
- memcpy函数和memmove函数的区别
- memmove和memcpy函数的区别及实现
- memcpy和memmove的区别与实现
- memcpy和memmove的区别与实现
- memcpy和memmove的区别与实现
- memcpy和memmove函数的实现
- memcpy和memmove函数的实现
- memcpy和memmove的函数内部实现
- memcpy memmove区别和实现
- memcpy memmove区别和实现
- memcpy memmove区别和实现
- ModelSim入门
- LeetCode合集
- 《算法导论》笔记 第23章 23.2 Kruskal 算法和 Prim 算法
- android 获取手机屏幕高度和宽度
- 在程序中写了一段代码向数据库中插入数据,出现了data too long for column 'name' at row 1的问题。
- Linux内核中memcpy和memmove函数的区别和实现
- mysql常用命令
- 学习的开始
- Shell入门之脚本管理学习笔记
- css中repeat-x与repeat-y什么意思。结合例子说明一下
- C语言中使用extern修饰函数要注意(转) .
- C++ const用法
- RSA 加解密算法
- .vimrc设置