您当前的位置: 首页 >  linux

Linux下的memcpy函数

发布时间:2022-02-20 09:30:00 ,浏览量:0

之前写过一篇关于 memcpy函数面试的文章

几个简单的笔试题

里面的代码使用的是char指针来实现,今天我们来看看Linux下面的memcpy

函数,它的实现上还是有一些巧妙的。

void * memcpy(void * dest, const void *src, size_t n)
{
  if (!(((unsigned long) dest ^ (unsigned long) src) & 7)) {
    __memcpy_aligned_up ((unsigned long) dest, (unsigned long) src,
             n);
    return dest;
  }
  __memcpy_unaligned_up ((unsigned long) dest, (unsigned long) src, n);
  return dest;
}

首先,函数会对参数判断地址是不是对齐的,如果是对齐的话,会调用对齐的内存拷贝函数,如果是不对齐的话,会调用不对其的函数。

正常情况下,地址都会是按4字节对齐的

看看__memcpy_aligned_up 函数

/*
 * Hmm.. Strange. The __asm__ here is there to make gcc use an integer register
 * for the load-store. I don't know why, but it would seem that using a floating
 * point register for the move seems to slow things down (very small difference,
 * though).
 *
 * Note the ordering to try to avoid load (and address generation) latencies.
 */
static inline void __memcpy_aligned_up (unsigned long d, unsigned long s,
          long n)
{
  ALIGN_DEST_TO8_UP(d,s,n);
  n -= 8;
  while (n >= 0) {
    unsigned long tmp;
    __asm__("ldq %0,%1":"=r" (tmp):"m" (*(unsigned long *) s));
    n -= 8;
    s += 8;
    *(unsigned long *) d = tmp;
    d += 8;
  }
  n += 8;
  DO_REST_ALIGNED_UP(d,s,n);
}

我们直接看代码操作就很清楚了,是按照8个字节来做的偏移

我写了个测试程序,测试程序和内核代码有一些小出入,主要是我用的是devc++来写代码,unsigned long并不是8字节。

测试代码如下

#include 
#include 

void * cris_memcpy(void *out, const void *in, unsigned int length) {
  if (!(((unsigned long) out ^ (unsigned long) in) & 7)) {
    printf("aligned\n");
  } 
  if (out == NULL || in == NULL) {
    return NULL;
  }

  while (length) {
    *(char*)out++ = *(char*)in++;
    length = length - 1;
  }
        
  return out;
}

typedef unsigned long long usize8_t;

static inline void __memcpy_aligned_up (usize8_t d, usize8_t s,
          long n) {
  if (!(((usize8_t) d ^ (usize8_t) s) & 7)) {
      printf("aligned\n");
    } 
  //n -= 8;
  printf("%d %d\n",n,sizeof(usize8_t));
  while (n >= 0) {
    usize8_t tmp;
    tmp = *(usize8_t *) s;
    n -= 8;
    s += 8;
    *(usize8_t *) d = tmp;
    d += 8;
  }
  n += 8;
}

int main() {
  char a[20] = "happy new year";
  char b[20];
  char c[20];
  
  cris_memcpy(&b, &a, strlen(a));
  __memcpy_aligned_up(&c, &a, strlen(a));
  printf("a=%s\n",a);
  printf("b=%s\n",b);
  printf("c=%s\n",c);
  return 0;
}

代码输出

0364e1f9cc4945fae97549b03db774c6.png

5a18ee0218a16bef4f6e39461fbe377e.png

最后,如果觉得不错,大家顺手点个赞,转发就是对我最大的鼓励和支持!

1855b75e97b4e92c1587458324989b5c.png

长按识别二维码关注公众号

关注
打赏
1688896170
查看更多评论

暂无认证

  • 0浏览

    0关注

    110253博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.4898s