您的位置:首页 > 其它

Spiceserver内存操作相关函数的使用

2016-05-10 10:57 676 查看
    Spiceserver内存操作部分也是整个项目用的比较多的模块,它自己封装了一套内存操作的函数,要掌握Spiceserver必须要掌握这些函数的使用,本篇我主要介绍一下我在阅读和使用这些函数及宏的一些理解,可能不是很全面,甚至理解不是很到位,后面有新的理解和发现再对blog进行更新。

内存操作底层相关函数

void *spice_malloc(size_t n_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE(1);
void *spice_malloc0(size_t n_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE(1);
void *spice_realloc(void *mem, size_t n_bytes) SPICE_GNUC_WARN_UNUSED_RESULT;
void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2);
void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size) SPICE_GNUC_MALLOC;
void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2);
void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_WARN_UNUSED_RESULT;

有关gcc编译优化

    我们看到上面一些自定义内存分配函数都有两个修饰的宏,一个是SPICE_GNUC_MALLOC一个是SPICE_GNUC_ALLOC_SIZE(1)或或者SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2),他们的定义如下:
#define SPICE_GNUC_MALLOC __attribute__((__malloc__))
#define SPICE_GNUC_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
#define SPICE_GNUC_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y)))
  
 有关这些宏的定义在https://developer.gnome.org/glib/stable/glib-Miscellaneous-Macros.html中可以找到。
    __attribute__((__malloc__)) 的作用,英文解释如下:



   意思是函数声明了这个以后,gcc对该函数有个更好的优化,意思是函数要返回一个指针,并且保证这个指针不含有别名,也就是指针指向的内存不被其他指针所指向,表明是要新分配一个内存。

 __attribute__((__alloc_size__(x))) 英文解释如下:



    意思是函数声明这个后,返回一个指向内存的指针,内存的大小有第x个函数参数制定,例如:void *spice_malloc(size_t n_bytes)使用声明该属性后,返回的内存大小被第1个参数指定,也就是n_bytes指定。

  
__attribute__((__alloc_size__(x,y)))
  英文解释如下:



 
    同上面的差不多,只不过多了个参数,意思是返回内存大小同第x个参数和第y个参数有关,这个无需再解释了。

函数内部调用

  阅读了源码,发现这些函数内部的调用都是比较简单的:
   (1)spice_malloc:内部调用malloc函数,我们可以直接把它当做malloc来调用;
   (2)spice_malloc0:内部调用的是calloc,它和malloc的区别是calloc分配内存后会将内存块清零;
   (3)spice_realloc:内部调用realloc;
   (4)spice_malloc_n:内部调用的是spice_malloc,只是参数分成两个,一个是块的大小,一个是块的个数;
   (5)spice_malloc0_n:spice_malloc_n分配后再清零的效果;
   (6)spice_malloc_n_m:在spice_malloc_n的基础上再增加一个额外的大小,例如:有时候我们分配内存时需要再加上一个结构体头部;
   (7)spice_realloc_n:spice_realloc分配内存大小分成块和块数的形式。
    我们来看下spice_malloc函数源码吧,其他函数都差不多,就不一一列举了。
void *spice_malloc(size_t n_bytes)
{
void *mem;

if (SPICE_LIKELY(n_bytes)) {/* 用于判断n_bytes是不是不等于0 */
mem = malloc(n_bytes);

if (SPICE_LIKELY(mem != NULL)) {/* 分配内存不等于NULL */
return mem;
}

MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes);
}
return NULL;
}


内存块的使用Demo

    Spiceserver中比较常用的内存块结构:RedDataChunk、SpiceChunks,我这里简单写了一个有关它们使用的Demo,我先将一个文件内容读取到RedDataChunk结构中,然后将RedDataChunk结构中的数据拷贝到SpiceChunks中,使用了Spiceserver中的一些自定义函数,代码如下:

   

#include <unistd.h>
#include <stdio.h>
#include "mem.h"
#define PACKAGE_LEN 512

/* 读取文件,将文件内容保存在red_chunk中 */
void get_chunk_from_file(const char *filepath, RedDataChunk *red_chunk)
{
FILE *file = fopen("./test.txt", "rb");
if( file == NULL ){
return;
}
RedDataChunk *cur_chunk = red_chunk;
while(TRUE){
uint8_t *pBuff = spice_malloc0(PACKAGE_LEN+1);/* 分配内存 */
if( pBuff == NULL ){
break;
}
uint32_t read_len = fread(pBuff, 1, PACKAGE_LEN, file);
if( read_len > 0 ){
RedDataChunk *chunk = spice_new(RedDataChunk, 1);
chunk->data_size = read_len;
chunk->data = pBuff;
chunk ->prev_chunk = cur_chunk;
chunk->next_chunk = NULL;

cur_chunk->next_chunk = chunk;
cur_chunk = chunk;
}
else{/* 未能读到数据 */
free(pBuff);
break;
}
}

fclose(file);
}

/* 释放RedDataChunk结构内存 */
void free_red_chunk(RedDataChunk *red_chunk)
{
RedDataChunk *cur_chunk = red_chunk->next_chunk;
RedDataChunk *next_chunk;

while(cur_chunk){
next_chunk = cur_chunk->next_chunk;
free(cur_chunk);
cur_chunk = next_chunk;
}
}

/* 将保存在red_chunk中的数据拷贝到spice_chunks中 */
SpiceChunks *get_spicechunk(RedDataChunk *red_chunk)
{
int i;
SpiceChunks *data;
RedDataChunk *chunk;
/* 计算RedDataChunk块的个数注意要去除头结点 */
for (i = 0, chunk = red_chunk->next_chunk; chunk != NULL; chunk = chunk->next_chunk) {
i++;
}
data = spice_chunks_new(i);/* 分配SpiceChunks内存 */
data->data_size = 0;
data->flags |= SPICE_CHUNKS_FLAGS_FREE;
for (i = 0, chunk = red_chunk->next_chunk;
chunk != NULL && i < data->num_chunks;
chunk = chunk->next_chunk, i++) {
data->chunk[i].data  = chunk->data;
data->chunk[i].len   = chunk->data_size;
data->data_size     += chunk->data_size;
}
return data;
}

void print_chunks(SpiceChunks *chunks)
{
int i;
for(i=0; i<chunks->num_chunks; i++){
printf("%s", chunks->chunk[i].data);
}
}

int main(int argc, char **argv)
{
RedDataChunk red_chunks;
get_chunk_from_file( "./test.txt", &red_chunks );
SpiceChunks *spice_chunks = get_spicechunk(&red_chunks);
free_red_chunk(&red_chunks);
print_chunks(spice_chunks);/* 打印 */
spice_chunks_destroy(spice_chunks);
return 0;
}


   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spice 内存