【redis源码】(一)Zmalloc
Zmalloc是redis的基础,redis源码的阅读从Zmalloc开始,相信这个一个愉快的旅程,读优秀的代码,就像听音乐~ 好了开始吧头文件 Zmalloc.h,没什么好说的,声明了一些函数,具体的实现见Zmalloc.c
1:#ifndef _ZMALLOC_H
2:#define _ZMALLOC_H
3:
4:void *zmalloc(size_t size);
5:void *zcalloc(size_t size);
6:void *zrealloc(void *ptr, size_t size);
7:void zfree(void *ptr);
8:char *zstrdup(const char *s);
9:size_t zmalloc_used_memory(void);
10:void zmalloc_enable_thread_safeness(void);
11:float zmalloc_get_fragmentation_ratio(void);
12:size_t zmalloc_get_rss(void);
13:
14:#endif /* _ZMALLOC_H */
Zmalloc.c
1:#include
2:#include
3:#include
4:#include
5:#include "config.h"
6:#include "zmalloc.h"
7:
8:
9://PREFIX_SIZE用来记录malloc拿到的内存块的size,如果使用了google的tcmalloc库或者苹果的环境,可以使用系统函数获得内存块的大小,就不用这个区域来记录
10:#ifdef HAVE_MALLOC_SIZE
11:#define PREFIX_SIZE (0)
12:#else
13:#if defined(__sun)
14:#define PREFIX_SIZE (sizeof(long long))
15:#else
16:#define PREFIX_SIZE (sizeof(size_t))
17:#endif
18:#endif
19:
20:/* Explicitly override malloc/free etc when using tcmalloc. */
21://使用google的tcmalloc库作为底层的malloc函数
22:#if defined(USE_TCMALLOC)
23:#define malloc(size) tc_malloc(size)
24:#define calloc(count,size) tc_calloc(count,size)
25:#define realloc(ptr,size) tc_realloc(ptr,size)
26:#define free(ptr) tc_free(ptr)
27:#endif
28:
29://Zmalloc会在全局静态变量里记录已经申请的内存大小 static size_t used_memory = 0;
30:#define update_zmalloc_stat_alloc(__n,__size) do { \
31: size_t _n = (__n); \
32: //将记录的内存大小补齐sizeof(long)的倍数
33: if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
34: if (zmalloc_thread_safe) { \
35: pthread_mutex_lock(&used_memory_mutex);\
36: used_memory += _n; \
37: pthread_mutex_unlock(&used_memory_mutex); \
38: } else { \
39: used_memory += _n; \
40: } \
41:} while(0)
42:
43:#define update_zmalloc_stat_free(__n) do { \
44: size_t _n = (__n); \
45: if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
46: if (zmalloc_thread_safe) { \
47: pthread_mutex_lock(&used_memory_mutex);\
48: used_memory -= _n; \
49: pthread_mutex_unlock(&used_memory_mutex); \
50: } else { \
51: used_memory -= _n; \
52: } \
53:} while(0)
54:
55:static size_t used_memory = 0;
56:static int zmalloc_thread_safe = 0;
57:pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
58:
59://如果申请内存失败,发送SIGABRT信号通知程序
60:static void zmalloc_oom(size_t size) {
61: fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
62: size);
63: fflush(stderr);
64: abort();
65:}
66:
67://申请size大bytes的内存区域
68:void *zmalloc(size_t size) {
69: //实际申请size+PREFIX_SIZE大小的内存空间,其中,前PREFIX_SIZE的空间用来记录内存块大小
70: void *ptr = malloc(size+PREFIX_SIZE);
71:
72: if (!ptr) zmalloc_oom(size);
73:#ifdef HAVE_MALLOC_SIZE
74: update_zmalloc_stat_alloc(redis_malloc_size(ptr),size);
75: return ptr;
76:#else
77: //记录内存块大小
78: *((size_t*)ptr) = size;
79: update_zmalloc_stat_alloc(size+PREFIX_SIZE,size);
80: return (char*)ptr+PREFIX_SIZE;
81:#endif
82:}
83:
84://申请size个sizeof(byte)大的内存区域
85:void *zcalloc(size_t size) {
86: void *ptr = calloc(1, size+PREFIX_SIZE);
87:
88: if (!ptr) zmalloc_oom(size);
89:#ifdef HAVE_MALLOC_SIZE
90: update_zmalloc_stat_alloc(redis_malloc_size(ptr),size);
91: return ptr;
92:#else
93: *((size_t*)ptr) = size;
94: update_zmalloc_stat_alloc(size+PREFIX_SIZE,size);
95: return (char*)ptr+PREFIX_SIZE;
96:#endif
97:}
98:
99://重新分配size大小的内存
100:void *zrealloc(void *ptr, size_t size) {
101:#ifndef HAVE_MALLOC_SIZE
102: void *realptr;
103:#endif
104: size_t oldsize;
105: void *newptr;
106:
107: if (ptr == NULL) return zmalloc(size);
108:#ifdef HAVE_MALLOC_SIZE
109: oldsize = redis_malloc_size(ptr);
110: newptr = realloc(ptr,size);
111: if (!newptr) zmalloc_oom(size);
112:
113: update_zmalloc_stat_free(oldsize);
114: update_zmalloc_stat_alloc(redis_malloc_size(newptr),size);
115: return newptr;
116:#else
117: realptr = (char*)ptr-PREFIX_SIZE;
118: oldsize = *((size_t*)realptr);
119: newptr = realloc(realptr,size+PREFIX_SIZE);
120: if (!newptr) zmalloc_oom(size);
121:
122: *((size_t*)newptr) = size;
123: update_zmalloc_stat_free(oldsize);
124: update_zmalloc_stat_alloc(size,size);
125: return (char*)newptr+PREFIX_SIZE;
126:#endif
127:}
128:
129://释放ptr开始内存块,与zmalloc,zcalloc,zrealloc配对
130:void zfree(void *ptr) {
131:#ifndef HAVE_MALLOC_SIZE
132: void *realptr;
133: size_t oldsize;
134:#endif
135:
136: if (ptr == NULL) return;
137:#ifdef HAVE_MALLOC_SIZE
138: update_zmalloc_stat_free(redis_malloc_size(ptr));
139: free(ptr);
140:#else
141: realptr = (char*)ptr-PREFIX_SIZE;
142: oldsize = *((size_t*)realptr);
143: update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
144: free(realptr);
145:#endif
146:}
147:
148://复制字符串
149:char *zstrdup(const char *s) {
150: size_t l = strlen(s)+1;
151: char *p = zmalloc(l);
152:
153: memcpy(p,s,l);
154: return p;
155:}
156:
157://得到已申请内存块总大小
158:size_t zmalloc_used_memory(void) {
159: size_t um;
160:
161: if (zmalloc_thread_safe) pthread_mutex_lock(&used_memory_mutex);
162: um = used_memory;
163: if (zmalloc_thread_safe) pthread_mutex_unlock(&used_memory_mutex);
164: return um;
165:}
166:
167://设置线程安全zmalloc开关,即操作前lock
168:void zmalloc_enable_thread_safeness(void) {
169: zmalloc_thread_safe = 1;
170:}
171:
172:/* Get the RSS information in an OS-specific way.
173: *
174: * WARNING: the function zmalloc_get_rss() is not designed to be fast
175: * and may not be called in the busy loops where Redis tries to release
176: * memory expiring or swapping out objects.
177: *
178: * For this kind of "fast RSS reporting" usages use instead the
179: * function RedisEstimateRSS() that is a much faster (and less precise)
180: * version of the funciton. */
181:
182:#if defined(HAVE_PROCFS)
183:#include
184:#include
185:#include
186:#include
187:
188:size_t zmalloc_get_rss(void) {
189: //获取runtime的信息,获取byte为单位的page大小
190: int page = sysconf(_SC_PAGESIZE);
191: size_t rss;
192: char buf;
193: char filename;
194: int fd, count;
195: char *p, *x;
196:
197: snprintf(filename,256,"/proc/%d/stat",getpid());
198: if ((fd = open(filename,O_RDONLY)) == -1) return 0;
199: if (read(fd,buf,4096)
页:
[1]