http://www.tuicool.com/articles/3QbYfm
http://www.360doc.com/content/13/1216/17/12904276_337644353.shtml
buf_chunk_t*结构体见 这里
/********************************************************************//** Allocates a chunk of buffer frames. @return chunk, or NULL on failure */ static buf_chunk_t* buf_chunk_init( /*===========*/ buf_pool_t* buf_pool, /*!< in: buffer pool instance */ //实现 buf_chunk_t* chunk, /*!< out: chunk of buffers */ //实现 ulint mem_size) /*!< in: requested size in bytes */ { buf_block_t* block; byte* frame; ulint i; /* Round down to a multiple of page size, although it already should be. */ mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE); //mem_size处理为16K的倍数 /* Reserve space for the block descriptors. */ mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block) + (UNIV_PAGE_SIZE - ), UNIV_PAGE_SIZE); //再为block申请内存 chunk->mem_size = mem_size; chunk->mem = os_mem_alloc_large(&chunk->mem_size); //开始申请在内存 if (UNIV_UNLIKELY(chunk->mem == NULL)) { return(NULL); } /* Allocate the block descriptors from the start of the memory block. */ chunk->blocks = chunk->mem; //结构体描述中说这是一个数组,这里看作是把chunk->mem开始内存地址给他 /* Align a pointer to the first frame. Note that when os_large_page_size is smaller than UNIV_PAGE_SIZE, we may allocate one fewer block than requested. When it is bigger, we may allocate more blocks than requested. */ frame = ut_align(chunk->mem, UNIV_PAGE_SIZE); /** *通过while循环,使得第一个frame在最后一个block后面 */ chunk->size = chunk->mem_size / UNIV_PAGE_SIZE- (frame != chunk->mem); /* Subtract the space needed for block descriptors. */ { ulint size = chunk->size; /** *chunk->blocks+size 可理解为构建chunk->blocks数组 *假设size=2000 000 chunk->blocks+2000 000 为 第2000 000个数组的地址 *上面地址肯定大于第一次循环时的frame地址 * *例如: *frame = 0x0016 //假设,要与16k对齐 *chunk->blocks = 0x000 *size=2000 000 *第一次循环 *while(0<(byte*)(chunk->blocks+size){ frame=0x0016+16k=0x0032; size=2000 000 -1=1999 999 } *第二次循环 *while(0x0032<(byte*)(chunk->blocks+1999 999){ frame=0x0032+16k=0x0048 size=1999 998 } *依次循环,直到frame大于chunk->block+X size *此时chunk->size为N个frame */ while (frame < (byte*) (chunk->blocks + size)) { frame += UNIV_PAGE_SIZE; size--; } chunk->size = size; } /* Init block structs and assign frames for them. Then we assign the frames to the first blocks (we already mapped the memory above). */ block = chunk->blocks;//是个数组 for (i = chunk->size; i--; ) { /** *设置block对应的frame * block.page的状态为BUF_BLOCK_NOT_USED *每个block头结构的大小:MySQL 5.1,32位 304 bytes;64位800 bytes *将mem空间划分为两部分:前部分作为block结构的空间;后部分作为page的空间, *page空间每一个page的起始位置,必须按照page size对齐 *block结构起始位置,为mem空间的0号位置; *page空间的起始位置,为预留足够的block结构之后的第一个frame位置 */ buf_block_init(buf_pool, block, frame); //详见 UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE); /* Add the block to the free list */ UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page)); //将该block->page放入buf_pool->free双向链表的最后 详见 ut_d(block->page.in_free_list = TRUE); ut_ad(buf_pool_from_block(block) == buf_pool); block++; //block的内存地址+ sizeof(buf_block_t),可理解为数组下一个元素 frame += UNIV_PAGE_SIZE; //下一个frame,可理解为buff_pool中的缓存块 } #ifdef PFS_GROUP_BUFFER_SYNC pfs_register_buffer_block(chunk); #endif return(chunk); }
将mem空间划分为两部分:前部分作为block结构的空间;后部分作为
// page的空间,page空间每一个page的起始位置,必须按照page size对齐
// block结构起始位置,为mem空间的0号位置;
// page空间的起始位置,为预留足够的block结构之后的第一个frame位置