SDS修改

在sds.h中,定义sds为char* 类型
typedef char *sds;
 
然后就是
sdshdr5/8/16/32/64。的5种结构体,这五种都是使用了
__attribute__ ((__packed__))来进行手动内存对齐。
 
此外,sdshdr5从来没有使用过,只在内部使用flag位。len和alloc的成员变量都没有。只用把flags位的高五位来存储长度就行了,节省空间。对于其他几种类型,高五位也没有使用。而且在源码中,判断出类型位hdr5,在申请空间时会转化为8.
 
以sdshdr8为例子,其他的只是把uint的长度进行了改变。
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[];  
};
 
len:实际使用的长度,不包括\0
alloc:分配的内存长度,不包括\0
flags:区别5/8/16/32/64的标志位
buf[]:柔性数组
 
 
redis在申请内存的时候,会申请这么大的空间:
initlen + hdrlen + 1
hdrlen为struct占用的空间,initlen为字符串占用的空间,1是\0。
这个initlen会先做
char type = sdsReqType(initlen);
来判断到底使用多大的sds。
内存分配结束后才会对结构体进行赋值。
 
重要定义:SDS_HDR_VAR(T,s)
#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));
s = (char*)sh+hdrlen;
sh = trymalloc?
        s_trymalloc_usable(hdrlen+initlen+1, &usable) :
        s_malloc_usable(hdrlen+initlen+1, &usable);
 
usable是分配内存的大小,在分配内存时redis会做一下处理,比如说你总的字节需要3个,这个时候redis会往上寻找最近的sds字节大小,即sds8.
然后usable会做
usable = usable-hdrlen-1;
让usable等于空闲大小。
其中s是buf[]成员变量的地址。sh是所分配内存的首地址。
sizeof(struct sdshdr##T),因为buf[]是柔性数组,所以大小为0。所以这个sizeof的大小,就是前面的三个成员的大小。
##不多讲,c中的语法粘连
所以最后得到的结果就是sds的地址。
 
1234
initlen=4
根据initlen做type的判断。得到type的值,再和7做&操作,得到具体结构体sizeof的大小。例如我传入的1234,实际上用的是sds5,只有一个u char,1个字节。这里的
hdrlen就是1。所以整个sds的大小就等于struct所占字节数 + 字符数 + 1。
s是buf[]地址
fp=sh的地址。
之前为了统计used_memory内存信息,会对usable做内存对齐,统计malloc实际上分配的内存,这时候会再减回去。(即:malloc(1),实际上分配的内存是8字节,为了统计准确,redis会调用malloc_usable_size统计准确信息,然后会用used_memory和usable做atomicIncr原子加操作)
usable = usable-hdrlen-1;
posted @ 2024-02-09 21:49  拿什么救赎  阅读(24)  评论(0)    收藏  举报