Address: http://bbs.chinaunix.net/thread-2020986-1-1.html I recently read slab content. A simple structure analysis is provided. Let's take a look.
Here, I would like to thank HYL and Eric Xiao for their help.
The following is the text:
Main data structure:
Struct kmem_cache_s { /* 1) per-CPU data, touched during every alloc/free */ Struct array_cache * array [nr_cpus]; Unsigned int batchcount; Unsigned int limit; /* 2) touched by every alloc & free from the backend */ Struct kmem_list3 lists; /* NUMA: kmem_3list_t * nodelists [max_numnodes] */ Unsigned int objsize; Unsigned int flags;/* constant flags */ Unsigned int num;/* # Of objs per slab */ Unsigned int free_limit;/* upper limit of objects in the lists */ Spinlock_t spinlock;
/* 3) cache_grow/shrink */ /* Order of PGs per Slab (2 ^ N )*/ Unsigned int gfporder;
/* Force green flags, e.g. gfp_dma */ Unsigned int gfpflags;
Size_t color;/* cache coloring range */ Unsigned int colour_off;/* color offset */ Unsigned int colour_next;/* cache coloring */ Kmem_cache_t * slabp_cache; Unsigned int slab_size; Unsigned int dflags;/* dynamic flags */
/* Constructor func */ Void (* ctor) (void *, kmem_cache_t *, unsigned long );
/* De-constructor func */ Void (* dtor) (void *, kmem_cache_t *, unsigned long );
/* 4) cache creation/removal */ Const char * Name; Struct list_head next;
/* 5) Statistics */ # If stats Unsigned long num_active; Unsigned long num_allocations; Unsigned long high_mark; Unsigned long grown; Unsigned long reaped; Unsigned long errors; Unsigned long max_freeable; Unsigned long node_allocs; Atomic_t allochit; Atomic_t allocmiss; Atomic_t freehit; Atomic_t freemiss; # Endif # If debug Int dbghead; Int reallen; # Endif };
Struct slab { Struct list_head list; Unsigned long colouroff; Void * s_mem;/* Including color offset */ Unsigned int inuse;/* num of objs active in slab */ Kmem_bufctl_t free; };
Struct kmem_list3 { Struct list_head slabs_partial;/* partial list first, better ASM Code */ Struct list_head slabs_full; Struct list_head slabs_free; Unsigned long free_objects; Int free_touched; Unsigned long next_reap; Struct array_cache * shared; };
The cache is described by kmem_cache_t (struct kmem_cache_s. The slab is described by struct slab. Objec is described by kmem_bufctl_t.
All kmem_cache_t constitute the linked list cache_chain. The linked list is protected by the semaphore cache_chain_sem: Static struct semaphore cache_chain_sem; Static struct list_head cache_chain;
The first high-speed cache of cache_chain is cache_cache. It can be seen from the name. This is the cache. That is to say, it stores the cache descriptor of other caches.
High-speed cache is divided into two types: general and specpacific.
For general high-speed cache, It is cache_cache and 13 kmalloc caches. Among them, the size of the 13 kmalloc caches is geographically distributed: 32, 64, 128,... they are defined in the malloc_sizes table.
Specpacific's high-speed cache is created by kmem_cache_create.
When the kernel is started, the kmem_cache_init () function is initialized to initialize cache_chain. In fact, it creates a general high-speed cache and initializes the corresponding content.
Shows the overall cache_chain situation:
A cache contains several slabs, and each slab contains several objects. The final object is the memory used to store data. For cache, slab, Object Here, a chart on ulk3 is referenced to illustrate the relationship between them:
For each cache, each slab contains a fixed number of consecutive page boxes, represented by cache-> gfporder
For the specified cache, the object size is fixed, represented by cache-> objsize
In the cache, the number of objects in each slab is also fixed, represented by cache-> num.
Therefore, for the specified cache, the size of the slab is also fixed (sizeof (struct slab) + cachohhot-> num * sizeof (kmem_bufctl_t), represented by cachu-> slab_size
When creating a cache (kmem_cache_create (), we only need to specify the size of the object, that is, the value of cache-> objsize is determined by parameters (kmem_cache_create () alignment size according to alignment requirements) The number of objects in an slab and the size of the slab are calculated based on kmem_cache_t-> objsize.
For the cache descriptor kmem_cache_t, slab descriptor, and the Structure Relationship Between the object, as shown in:
To allocate an object from a cache, call kmem_cache_alloc () to implement the following: Kmem_cache_alloc (kmem_cache_t * cachu, unsigned long flag );
This section describes the basic concepts of High-speed cache. Next we will introduce how it is associated with the page box in memory.
Slab alloctor applies to the page box through buddy alloctor. In kmem_cache_alloc (), kmem_getpages () is called, and kmem_getpages () is called alloc_pages ().
After a page box is assigned to slab, pg_slab in page-> flag will be set to bits. At the same time, the LRU of the page descriptor will point to the corresponding cache and slab, as shown in:
The object descriptor is stored next to the slab descriptor. The object descriptor is in the size of cache-> slab_size. The slab descriptor is determined based on the size of cache-> objsize to be stored inside or outside slab. If it is stored internally, the slab Descriptor and object descriptor will be stored in the page box allocated by kmem_cache_alloc (). If it is stored externally, it will select an appropriate one from 13 kmalloc caches based on the size of cache-> slab_size.
An object descriptor is usually a short int value. For an slab, there are a total of cache-> num object descriptors. The object descriptor stores the subscript of the next idle object. It makes sense only when the object is idle. The value of the last object descriptor is bufctl_end, which is used to mark the end of the object.
Slab-> s_mem points to the address of the first object, Slab-> free points to the subscript of the next idle object. If there is no idle object, the subscript is bufctl_end.
Therefore, we can find the address of the first idle object through slab-> s_mem + slab-> free * cache-> objsize. Get the subscript of the next idle object through (kmem_bufctl_t *) (slab + 1) [slab-> free]
Is a simple example to illustrate the slab structure:
Here, we will introduce a chart on ulk3 for further explanation:
|