glibc 中内存拷贝函数memcpy()研究

2 篇文章 0 订阅

glibc内存拷贝函数memcpy()研究。

memcpy()函数源代码:

void *
memcpy (void *dstpp, const void *srcpp, size_t len)
{
  unsigned long int dstp = (long int) dstpp;
  unsigned long int srcp = (long int) srcpp;

  /* Copy from the beginning to the end.  */

  /* If there not too few bytes to copy, use word copy.  */
  if (len >= OP_T_THRES)   (NB:OP_T_THRES ==16)
    {
      /* Copy just a few bytes to make DSTP aligned.  */
      len -= (-dstp) % OPSIZ; (最牛逼的地方就是这个负号) (OPSIZ ==8)
      BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);(这个地方依然很牛逼)

      /* Copy whole pages from SRCP to DSTP by virtual address manipulation,
     as much as possible.  */

      PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);

      /* Copy from SRCP to DSTP taking advantage of the known alignment of
     DSTP.  Number of bytes remaining is put in the third argument,
     i.e. in LEN.  This number may vary from machine to machine.  */

      WORD_COPY_FWD (dstp, srcp, len, len);

      /* Fall out and copy the tail.  */
    }

  /* There are just a few bytes to copy.  Use byte memory operations.  */
  BYTE_COPY_FWD (dstp, srcp, len);

  return dstpp;
}

下面开始进行源代码的分析

第一步:

unsigned long int dstp = (long int) dstpp;
unsigned long int srcp = (long int) srcpp;

这两句代码的意思就是将有符号的整型转变成无符号的整型,变成无符号整型就可以使用下面那个牛逼的技巧。

第二步:

考虑到内存地址对齐的要求,程序是这么处理的,先对未对齐的地址进行处理,使其地址对齐,然后再进行对齐后的字节或页的拷贝。

len -= (-dstp) % OPSIZ;
BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);

这两句就是对未对齐地址的部分进行处理,注意前面的那个负号。
这里写图片描述

第三步

当初步完成后,内存地址对齐,可以进行按页后者字进行拷贝。

# define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes)             \
  do                                          \
    {                                         \
      if ((nbytes) >= PAGE_COPY_THRESHOLD &&                      \
      PAGE_OFFSET ((dstp) - (srcp)) == 0)                     \
    {                                     \
      /* The amount to copy is past the threshold for copying         \
         pages virtually with kernel VM operations, and the           \
         source and destination addresses have the same alignment.  */    \
      size_t nbytes_before = PAGE_OFFSET (-(dstp));               \
      if (nbytes_before != 0)                         \
        {                                     \
          /* First copy the words before the first page boundary.  */     \
          WORD_COPY_FWD (dstp, srcp, nbytes_left, nbytes_before);         \
          assert (nbytes_left == 0);                      \
          nbytes -= nbytes_before;                        \
        }                                     \
      PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes);            \
    }                                     \
    } while (0)

/* The page size is always a power of two, so we can avoid modulo division.  */
# define PAGE_OFFSET(n) ((n) & (PAGE_SIZE - 1))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值