Linux Kernel Architecture

(Jacob Rumans) #1

Chapter3:MemoryManagement


This lengthy structure is divided into multiple parts as indicated by the comments in the kernel sources.^32


The initial elements are concerned with CPU-specific data accessed by the kernel during each allocation,
touched upon in Section 3-46.


❑ arrayis a pointer to an array with an entry for each CPU in the system. Each entry contains a
further pointer to an instance of thearray_cachestructure discussed below.
❑ batchcountspecifies the number of objects to be taken from the slabs of a cache and added to the
per-CPU list if it is empty. It also indicates the number of objects to be allocated when a cache is
grown.
❑ limitspecifies the maximum number of objects that may be held in a per-CPU list. If this value
is exceeded, the kernel returns the number of objects defined inbatchcountto the slabs (if the
kernel then shrinks the caches, memory is returned from the slabs to the buddy system).
❑ buffer_sizespecifies the size of the objects managed in the cache.^33
❑ Suppose that the kernel has a pointer to an element in a slab and wants to determine the corre-
sponding object index. The easiest way to do this is to divide the offset of the pointer compared
to the start of the slab area by the object size. Consider, for example, that a slab area starts at
memory location 100, each object requires 5 bytes, and the object in question is located at mem-
ory position 115. The offset between the slab start and the object is 115− 100 =15, so the object
index is 15/ 5 =3. Unfortunately, divisions are slow on some older machines.
Since multiplications are much faster on these machines, the kernel uses the so-called
Newton-Raphsontechnique, which requires only multiplications and bit shifts. While the
mathematical details are not interesting for our purposes (they can be found in any standard
textbook), we need to know that instead of computingC = A/B, the kernel can also employC
= reciprocal_divide(A, reciprocal_value(B))— both functions are provided as library
routines. Since the object size in a slab is constant, the kernel can store the recpirocal value of
buffer_sizeinrecpirocal_buffer_size, which can be used later when the division must be
computed.

The kernel provides an instance ofarray_cachefor each system processor. This structure is defined as
follows:


mm/slab.c
struct array_cache {
unsigned int avail;
unsigned int limit;
unsigned int batchcount;
unsigned int touched;
spinlock_t lock;
void *entry[];
};

(^32) If slab debugging is enabled, another part with statistical information gathered by the kernel concludes the structure.
(^33) If slab debugging is enabled, the buffer size can differ from the object size because extra padding (in addition to the padding used
to align the objects properly) is introduced per element. In this case, a second variable denotes the real size of the object.

Free download pdf