malloc implementation of the Lnux kernel (Oracle's cache buffer shadow)
This article original for freas_1990, reprint please indicate source: http://blog.csdn.net/freas_1990/article/details/12845059
This article introduces the principle of malloc, and students interested in mm (or interested in Oracle internal implementations) can find content of interest in this article.
Malloc is mainly supported by two structures.
struct Bucket_desc {/* bytes */void *page; struct bucket_desc *next; void *freeptr; unsigned short refcnt ; unsigned short bucket_size;};
This structure is a bucket descriptor. All objects are connected through a chain table.
struct _bucket_dir {/* 8 bytes */intsize;struct bucket_desc*chain;};
This is the directory of buckets.
I have drawn two graphs to describe how a page (the pages; 4k) is described by these two structures.
A 4k page is assigned to a bucket with a size of just bytes
A 4k page is assigned to a bucket with a size of just bytes .
So how are these data structures initialized?
First, in the kernel code, the following data is hardcoded.
struct _bucket_dir bucket_dir[] = {{, (struct Bucket_desc *) 0},{, (struct Bucket_desc *) 0},{, (struct BUCKET_DESC *) 0},{, (struct Bucket_desc *) 0},{, (struct Bucket_desc *) 0},{, (struct Bucket_desc *) 0},{1024x768, (struct Bucke T_DESC *) 0},{2048, (struct Bucket_desc *) 0},{4096, (struct Bucket_desc *) 0},{0, (struct Bucket_desc *) 0}}; /* End of list marker */
Defines the degree of granularity from 16 to the second-party growth.
I wrote a simplified pseudo-code to describe the whole process.
pseudo code for malloc :
Procedure:get the Bucket_desc with object size (for example, bytes) if (search Bucket_desc list for free space) {return Bdesc->freeptr} else {if (INIT_BUCKET_DESC) {return bdesc->freeptr} else {panic ("Init_bucket_desc Error")}} Init_bucket_desc:if (page = get_one_page) {sepreated the page (4k) with Dir->sizelink all the pieces} else {panic ("Get Pag E error ")}end procedure
pseudo code for free:
Procedure:get the Bucket_desc with object size (for example, bytes) if (search Bucket_desc list for the related Bucket_desc {Erase bdesc->freeptrbdesc->refcnt--if (bdesc->refcnt = = 0) {if (whole page NULL) {if (!free_page (bdesc-> Page) {Panic ("Free_page Error")}}}} else {panic ("Input pointer not right")}end procedure
Thinking about the data structure performance:
The main data structure here is a one-way linked list, the time to find a complex O (N), is a violent search.
Using an array of 10 elements, the data structure cannot be loaded when the memory is used too large.
perhaps using a hash or a tree structure can solve the problem.
However, for memory 20 years ago, fully able to cope with:)
malloc implementation of the Lnux kernel (Oracle's cache buffer shadow)