免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8717 | 回复: 4
打印 上一主题 下一主题

[函数] BSD的memcpy()函数源码 大家讨论讨论:) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-12-06 17:20 |只看该作者 |倒序浏览
本帖最后由 JohnBull 于 2011-05-11 17:39 编辑

#include <sys/cdefs.h>;
#include <string.h>;

/*
* sizeof(word) MUST BE A POWER OF TWO
* SO THAT wmask BELOW IS ALL ONES
*/
typedef    int word;        /* "word" used for optimal copy speed */

#define    wsize    sizeof(word)
#define    wmask    (wsize - 1)

/*
* Copy a block of memory, handling overlap.
* This is the routine that actually implements
* (the portable versions of) bcopy, memcpy, and memmove.
* length 以Byte作为度量单位
*/
#ifdef MEMCOPY
void *
memcpy(dst0, src0, length)
#else
#ifdef MEMMOVE
void *
memmove(dst0, src0, length)
#else
void
bcopy(src0, dst0, length)
#endif
#endif
    void *dst0;
    const void *src0;
    register size_t length;
{
    register char *dst = dst0;
    register const char *src = src0;
    register size_t t;

    if (length == 0 || dst == src)        /* nothing to do */
        goto done;

    /*
     * Macros: loop-t-times; and loop-t-times, t>;0
     */
#define    TLOOP(s) if (t) TLOOP1(s)
#define    TLOOP1(s) do { s; } while (--t)

    if ((unsigned long)dst < (unsigned long)src) {
        /*
         * Copy forward.
         */
        t = (int)src;    /* only need low bits */
                /*这样做的目的是由于下面的TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize)拷贝用的是32位为一个单位
                 *所以 这是的指针所指向的地址是最后两位是00(这个想法我还没验证)所以在匹配之前一定要将DES 和 SRC指针对齐到最后两位为00才行
                 */
        if ((t | (int)dst) & wmask) {  // 如果源和目标地址的最后两位不是00的话
            /* 对齐操作数???   
             * Try to align operands.  This cannot be done
             * unless the low bits match.
             */
            if ((t ^ (int)dst) & wmask || length < wsize)   
                t = length;               //如果目标和源的地址最后两位参差不齐如 11 10 只能以Byte为单位拷贝
            else
                t = wsize - (t & wmask);  //如果目标和源的地址最后两位如 10 10相等的话 把他们同时移到00来做
            length -= t;
            TLOOP1(*dst++ = *src++);
        }
        /*
         * Copy whole words, then mop up any trailing bytes.
         */
        t = length / wsize;
        TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
        t = length & wmask;
        TLOOP(*dst++ = *src++);
    } else {
        /*
         * Copy backwards.  Otherwise essentially the same.
         * Alignment works as before, except that it takes
         * (t&wmask) bytes to align, not wsize-(t&wmask).
         */
        src += length;
        dst += length;
        t = (int)src;
        if ((t | (int)dst) & wmask) {
            if ((t ^ (int)dst) & wmask || length <= wsize)
                t = length;
            else
                t &= wmask;
            length -= t;
            TLOOP1(*--dst = *--src);
        }
        t = length / wsize;
        TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
        t = length & wmask;
        TLOOP(*--dst = *--src);
    }
done:
#if defined(MEMCOPY) || defined(MEMMOVE)
    return (dst0);
#else
    return;
#endif
} 其中中文注释是我自己加的,不知道对不对
不过我对函数中先将DES和SRC指针对齐(align) 就是我加注释的那部分的意义还不是很明白,我觉得直接进行字赋值操作 最后把结尾的部分补齐就行了
呵呵,不明白为什么作者要加这一段 大家讨论讨论

论坛徽章:
0
2 [报告]
发表于 2004-12-07 10:02 |只看该作者

BSD的memcpy()函数源码 大家讨论讨论:)

看了《C 专家编程》 终于明白了代码的意思 ,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 型指针。
   呵呵 看了《C 专家编程》之后茅塞顿开,觉得上面的代码写的真是漂亮。以后要好好学习

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
3 [报告]
发表于 2004-12-07 10:32 |只看该作者

BSD的memcpy()函数源码 大家讨论讨论:)

嗯,这个例程写的确实不错。不过很多地方是空判断,觉得还有改进的余地。

论坛徽章:
0
4 [报告]
发表于 2004-12-07 19:59 |只看该作者

BSD的memcpy()函数源码 大家讨论讨论:)

这个程序真是经典!
pfpf。。。。。。如果我哪天能有这种能力。。。。。。。

论坛徽章:
0
5 [报告]
发表于 2011-05-11 15:25 |只看该作者
看了清楚好多,茅塞顿开啊,谢谢了,
一直不清楚是如何实现str dst同时对齐
现在知道了,如果str dst最后两位参数不同
是不可能对其的,哈哈
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP