美文网首页
glibc的memset函数解析

glibc的memset函数解析

作者: JonorZhang | 来源:发表于2021-04-28 23:06 被阅读0次

先上原代码:

void *memset (void *dstpp, int c, size_t len)
{
    long int dstp = (long int) dstpp;
    
    if (len >= 8)
    {
        size_t xlen;
        op_t cccc;
        
        cccc = (unsigned char) c;
        cccc |= cccc << 8;
        cccc |= cccc << 16;
        if (OPSIZ > 4)
        /* Do the shift in two steps to avoid warning if long has 32 bits.  */
            cccc |= (cccc << 16) << 16;
        
        /* There are at least some bytes to set.
         No need to test for LEN == 0 in this alignment loop.  */
        while (dstp % OPSIZ != 0)
        {
            ((byte *) dstp)[0] = c;
            dstp += 1;
            len -= 1;
        }
        
        /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
        xlen = len / (OPSIZ * 8);
        while (xlen > 0)
        {
            ((op_t *) dstp)[0] = cccc;
            ((op_t *) dstp)[1] = cccc;
            ((op_t *) dstp)[2] = cccc;
            ((op_t *) dstp)[3] = cccc;
            ((op_t *) dstp)[4] = cccc;
            ((op_t *) dstp)[5] = cccc;
            ((op_t *) dstp)[6] = cccc;
            ((op_t *) dstp)[7] = cccc;
            dstp += 8 * OPSIZ;
            xlen -= 1;
        }
        len %= OPSIZ * 8;
        
        /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
        xlen = len / OPSIZ;
        while (xlen > 0)
        {
            ((op_t *) dstp)[0] = cccc;
            dstp += OPSIZ;
            xlen -= 1;
        }
        len %= OPSIZ;
    }
    
    /* Write the last few bytes.  */
    while (len > 0)
    {
        ((byte *) dstp)[0] = c;
        dstp += 1;
        len -= 1;
    }
    
    return dstpp;
}

灵魂发问:为什么有4次while循环,各有什么作用?

以下为个人理解,不正之处还请指出:

  • 数据总线决定了一次性最多可访问数据的位数(常见的计算机是32位或64位),位数等于[字]长,也就是说机器一次性最多可访问一个[字] 长,因此,在批量内存访问中,按[字]访问最高效,我们看到这段代码也是尽可能按[字]写入的;
    1)什么是内存对齐?将要操作的内存地址指针偏移到能整除[字]长的位置即可;
    2)为什么要内存对齐?例如,非对齐情况下读取一个字长的内存,计算机需分别读取目标内存左右两个字的内容组合成我们所需的字,这就增加了额外操作(这里的额外操作是硬件层面的,汇编代码就一句);而对齐之后,计算机只需读取目标字的内容即可,无需再组合,因此寻址效率更高, 进而提高内存操作指令的执行效率;

  • 第一个while是准备工作,操作目标为未对齐的内存部分,执行完这个while之后内存就对齐了,之后第二、第三个while执行效率会更高;

  • 第二个while是主循环,操作目标为已进行字节对齐的大块内存,大部分内存赋值操作在这里进行,但为什么是8次赋值为一个循环周期?也就是8倍内存单元为一块?
    1)为了尽可能减少边界判断和辅助变量赋值操作次数,以提高内存赋值操作在循环周期里的比重;
    2)8倍是经典值,符合一般申请的内存大小分布规律,大于8或小于8都会减少这个while的执行率,说白了就是要提高这个while被执行的几率;

  • 第三个while是次循环,操作目标为已进行字节对齐但又不足8倍对齐单元的内存部分,每次为一个对齐单元赋值;

  • 第四个while是收尾工作,操作目标为余下的不足一个对齐单元的部分,这部分只能挨个字节赋值了;

底层函数之所以执行效率高,除了对计算机原理有深刻理解,设计也是很巧妙啊

orz

相关文章

  • glibc的memset函数解析

    先上原代码: 灵魂发问:为什么有4次while循环,各有什么作用? 以下为个人理解,不正之处还请指出: 数据总线决...

  • iOS 通过HOST获取IP地址和类型

    函数解析 memset() memset()函数原型是extern void *memset(void *buff...

  • Mem系列函数介绍

    函数名称: memset 函数原型: void *memset(void *s, int ch, size...

  • memery

    memset函数 void *memset(void *s, int ch,size_tn); 函数解释:将s中当...

  • C++中memset函数的用法

    memset:char型初始化函数 头文件: 或 函数原型:void *memset(vo...

  • memset的含义及作用

    memset()函数原型是extern void *memset(void *buffer, int c, int...

  • memset的用法总结

    memset()函数原型是extern void *memset(void *buffer, int c, int...

  • 无标题文章

    今天做题卡在MEMSET函数的使用上了,本来以为int a[100]; memset(a, MAX,sizeof(...

  • memset 函数

  • memset函数

    将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值, 第一个值为指定的内存地址,块的大小由...

网友评论

      本文标题:glibc的memset函数解析

      本文链接:https://www.haomeiwen.com/subject/woabrltx.html