1 #include <sys/cdefs.h>;
2 #include <string.h>;
3
4 /*
5 * sizeof(word) MUST BE A POWER OF TWO
6 * SO THAT wmask BELOW IS ALL ONES
7 */
8 typedef int word; /* "word" used for optimal copy speed */
9
10 #define wsize sizeof(word)
11 #define wmask (wsize - 1)
12
13 /*
14 * Copy a block of memory, handling overlap.
15 * This is the routine that actually implements
16 * (the portable versions of) bcopy, memcpy, and memmove.
17 * length 以Byte作为度量单位
18 */
19 #ifdef MEMCOPY
20 void *
21 memcpy(dst0, src0, length)
22 #else
23 #ifdef MEMMOVE
24 void *
25 memmove(dst0, src0, length)
26 #else
27 void
28 bcopy(src0, dst0, length)
29 #endif
30 #endif
31 void *dst0;
32 const void *src0;
33 register size_t length;
34 {
35 register char *dst = dst0;
36 register const char *src = src0;
37 register size_t t;
38
39 if (length == 0 || dst == src) /* nothing to do */
40 goto done;
41
42 /*
43 * Macros: loop-t-times; and loop-t-times, t>;0
44 */
45 #define TLOOP(s) if (t) TLOOP1(s)
46 #define TLOOP1(s) do { s; } while (--t)
47
48 if ((unsigned long)dst < (unsigned long)src) {
49 /*
50 * Copy forward.
51 */
52 t = (int)src; /* only need low bits */
53 /*这样做的目的是由于下面的TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize)拷贝用的是32位为一个单位
54 *所以 这是的指针所指向的地址是最后两位是00(这个想法我还没验证)所以在匹配之前一定要将DES 和 SRC指针对齐到最后两位为00才行
55 */
56 if ((t | (int)dst) & wmask) { // 如果源和目标地址的最后两位不是00的话
57 /* 对齐操作数???
58 * Try to align operands. This cannot be done
59 * unless the low bits match.
60 */
61 if ((t ^ (int)dst) & wmask || length < wsize)
62 t = length; //如果目标和源的地址最后两位参差不齐如 11 10 只能以Byte为单位拷贝
63 else
64 t = wsize - (t & wmask); //如果目标和源的地址最后两位如 10 10相等的话 把他们同时移到00来做
65 length -= t;
66 TLOOP1(*dst++ = *src++);
67 }
68 /*
69 * Copy whole words, then mop up any trailing bytes.
70 */
71 t = length / wsize;
72 TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
73 t = length & wmask;
74 TLOOP(*dst++ = *src++);
75 } else {
76 /*
77 * Copy backwards. Otherwise essentially the same.
78 * Alignment works as before, except that it takes
79 * (t&wmask) bytes to align, not wsize-(t&wmask).
80 */
81 src += length;
82 dst += length;
83 t = (int)src;
84 if ((t | (int)dst) & wmask) {
85 if ((t ^ (int)dst) & wmask || length <= wsize)
86 t = length;
87 else
88 t &= wmask;
89 length -= t;
90 TLOOP1(*--dst = *--src);
91 }
92 t = length / wsize;
93 TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
94 t = length & wmask;
95 TLOOP(*--dst = *--src);
96 }
97 done:
98 #if defined(MEMCOPY) || defined(MEMMOVE)
99 return (dst0);
100 #else
101 return;
102 #endif
103 }
BSD的memcpy是经过优化的代码,主要是从SRC到DES的赋值操作时,使用了WORD(也就是INT)型指针,每次拷贝32位。他正好符合CACHE中32位的原则,效率比较高。大概是8位赋值的效率的好几倍。
但是计算机架构中,数据项只能存在于于地址是数据项的大小的整数倍上,如DOUBLE型只能存在于8的整数倍如8008而不能存在于1006的地址上,如果跨界存取就有可能使原子数据项跨越一个页或CACHE的边界,不但会影响拷贝性能,严重时还会产生BUS ERROR(core dumped)的错误,所以在使用WORD指针前一定要将DES和SRC指针对齐到被4(sizeof(int) = 4 对于32位系统而言) 整除的位置。但如果DES和SRC的最后两位不相等的话,不管怎么移都不可能保证DES和SRC指针移动相等的长度后都可以被4整除,所以这时只能采用每8位拷贝一次,只能采用CHAR 型指针。