Redis sds 的源码中,使用了 __attribute__ ((__packed__)) ,一般情况下,结构体会按其所有变量大小的最小公倍数做字节对齐,而用packed修饰以后,结构体则变为按1字节进行对齐。这个最小公倍数如何进行理解呢?

以以下结构进行举例:

#include <stdio.h>typedef struct MemAlign
{  char a[18];  double b;     char c;  int d;    short e;
}MemAlign;typedef struct __attribute__ ((__packed__))  MemAlignPacked
{  char a[18];  double b;     char c;  int d;    short e;
}MemAlignPacked;  int main(void){struct MemAlign m;struct MemAlignPacked mp;printf("========>%d", sizeof(m));printf("========>%d", sizeof(mp));
}

内存存放数据是为了给CPU进行使用,而CPU访问内存数据时会受到地址总线宽度的限制,并且CPU从内存中获取数据时起始地址必须是地址总线宽度的倍数,也就是说CPU是将内存分为一块一块的,块的大小取决于地址总线宽度,并且CPU读取数据也是一块一块读取的,块的大小称为(memory granularity)内存读取粒度。

上面的结构中,有char a[18]这个属性,说明这个属性是占个字节的,在32位CPU的内存模型中,以4个字节对齐(如下图1),属性char a[18]因为占了18个字节,会需要补齐2个字节达到4的最小公倍数20,然后接着分配double b的内存地址(如下图2)。而使用了__packed__修饰以后,就不需要补齐。

而在64位CPU的内存模型中,以8个字节进行对齐(如下图1)。则案例结构如下图2。我的mac是64位的,跑文章开始的代码跑出的结果和猜测的一样。

所以在redis的sds的源码中,出现的sdshdr5 、sdshdr8、sdshdr16、sdshdr32、sdshdr64,都使用了 __attribute__ ((__packed__))进行紧凑排列。好处在于节省内存和方便buf[-1]取到flags地址,获取类型更加方便。

/* Note: sdshdr5 is never used, we just access the flags byte directly.* However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 3 lsb of type, and 5 msb of string length */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* used */uint8_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {uint16_t len; /* used */uint16_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* used */uint32_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {uint64_t len; /* used */uint64_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};

一般情况下windows64位一般使用LLP64模型,64位Unix,Linux使用的是LP64模型

Datetype LP64 ILP64 LLP64 ILP32 LP32
char 8 8 8 8 8
short 16 16 16 16 16
int 32 64 32 32 16
long 64 64 32 32 32
long long 64 64 64 64 64
pointer 64 64 64 32 32

参考:

https://juejin.cn/post/7074538808259117064

https://blog.csdn.net/wejack/article/details/127686029

https://blog.csdn.net/weixin_40997360/article/details/79948968

https://zhuanlan.zhihu.com/p/140063999

https://juejin.cn/post/6922352059517779976

Redis sds packed对齐理解相关推荐

  1. redis sds的申请扩容源码

    sds是redis中简单的字符串实现 sdsnewlen()方法可以用来申请sds. sds sdsnewlen(const void *init, size_t initlen); 第一个参数是sd ...

  2. Vins_mono重力对齐理解

    // 6 通过将重力旋转到z轴上,得到世界坐标系与摄像机坐标系c0之间的旋转矩阵rot_diff// 此处解算得到的g是枢纽帧下的重力// 关于vins是4自由度的理解 四自由度应该指的是 x y z ...

  3. 缓存成神路:Redis读写分离难以理解?一文解析Redis读写分离技术

    背景 云数据库Redis版不管主从版还是集群规格,replica作为备库不对外提供服务,只有在发生HA的时候,replica提升为master后才承担读写流量.这种架构读写请求都在master上完成, ...

  4. linux ls 输出对齐,理解 Linux 中 `ls` 的输出

    ls 的输出会因各 Linux 版本变种而略有差异,这里只讨论一般情况下的输出. 下面是来自 man page 关于 ls 的描述: $ man ls ls - list directory cont ...

  5. 对于redis底层框架的理解(一)

    近期学习了redis底层框架,好多东西之前都没听说过,算是大开眼界了. 先梳理下redis正常的通讯流程吧 首先服务器启动都有主函数main,这个main函数就在redis.c里 首先是initser ...

  6. redis并发锁 thinkphp5_资深架构师经典总结:Redis分布式锁实现理解

    在Redis上,可以通过对key值的独占来实现分布式锁,表面上看,Redis可以简单快捷通过set key这一独占的方式来实现,也有许多重复性轮子,但实际情况并非如此. 总得来说,Redis实现分布式 ...

  7. c语言实现string sds,redis学习 - sds字符串

    redis学习 - sds字符串 Redis 设计与实现:如果想要知道redis底层,这本书可以给予不少的帮助,非常推荐每一位学习redis的同学去翻一翻. sds字符串建议多看看源代码的实现,这篇文 ...

  8. Redis源码分析(sds)

    源码版本:redis-4.0.1 源码位置:https://github.com/antirez/sds 一.SDS简介 sds (Simple Dynamic String),Simple的意思是简 ...

  9. 一、redis原理之string底层数据结构SDS

    一.前言 我们说Redis 是用 C 语言写的,,但是对于Redis的字符串,却不是 C 语言中的字符串(即以空字符'\0'结尾的字符数组),它是自定义的数据结构SDS(simple dynamic ...

最新文章

  1. 生物识别技术在我们日常生活中的应用
  2. C# 轻量级ORM 编写思维
  3. 微信小程序实战篇:商品属性联动选择(案例)
  4. centos7开放80端口_Centos7.4系统 httpd模式搭建文件服务器
  5. hdu 2063 过山车(模板)
  6. [bzoj2588] Count on a tree
  7. java spark命令行执行参数
  8. c++按行读取txt文件中的内容,并按特定字符分割
  9. 国家信息安全水平考试NISP一级模拟题(01)
  10. 视频教程-Linux基础入门视频课程-Linux
  11. 【转载】ASP.Net请求处理机制初步探索之旅 - Part 3 管道
  12. openwrt之mwan3负载均衡·多线多拨
  13. PHP调用wsdl接口实例化SoapClient抛出异常
  14. 今天教你5种爆款标题,自媒体短视频标题写得好,月入过万少不了
  15. 手机端的日期选择的插件
  16. JAVA-多线程 三 {多线程状态}JAVA从基础开始 -- 3
  17. Week2 Assignment - Princeton-Algorithms-PartI
  18. 我对计算机的看法英语作文,我对网络的看法 My Concepts on Internet 英语作文范文...
  19. Office 2016 定制安装工具 v1.0 | Office 2016 自定义安装组件
  20. zw2012激活方法

热门文章

  1. python是一种解释型编程语言_python是不是解释型语言
  2. 思-中国移动通信研究院的面试题
  3. C语言循环语句实训项目,C语言程序设计与项目实训
  4. html输入框是一条横线,html把输入的文本框变成一个下横线css样式
  5. 手眼标定+jaka机械臂
  6. C# 图书管理系统(MySQL)——属性设计(三)
  7. 网络项目寻找创业合作伙伴
  8. python做社会网络分析_科学网-python 社会网络分析工具之igraph-郗强的博文
  9. word关闭未响应_写了两小时的文档没保存?!一个word小技巧来拯救
  10. 领英更新改版后,怎么登录国际版领英继续搜索开发客户?详细教程