2.3 memory pool Allocation Sub-allocator2.3.1 Allocation Sub-Overview although we can use the malloc function to directly allocate apr_memnode_t nodes, this approach is not recommended in Apache. In fact, most of the memory in Apache is allocated by the Memory Allocation Sub-allocator. It hides the actual internal allocation details and provides several simple interfaces for memory pool function calls. The Memory Allocation Sub-item belongs to the internal data structure and cannot be directly called by external programs. The Memory Allocation Sub-(hereinafter referred to as the Allocation Sub-) is defined in the apr_pools.c file as follows: struct apr_allocator_t {apr_uint32_t max_index; apr_uint32_t max_free_index; then current_free_index; # If apr_has_threads * mutex; # endif/* apr_has_threads */apr_pool_t * owner; apr_memnode_t * free [max_index] ;}; the most important element in this structure is the free array. Each element of the array is an apr_memnode_t address, point to an apr_memnode_t node linked list. When the memory is allocated, it is allocated from the actual node. After the memory is used, it is returned to the allocation subaccount. However, the node size in the free linked list is not exactly the same. It depends on the index of the current linked list in the free array. Here, the Index of the Free array has two meanings: the first layer, the actual index of the node linked list in the array, which is the most superficial meaning; in addition, it also indicates the node size in the current linked list. The larger the index, the larger the node. The size of all nodes in the same linked list is completely equal. The size of the nodes has the following relationship with the index of the linked list where the nodes are located: node size = 8 K + 4 K * (index-1) therefore, if the Linked List index is 2, all the nodes in the linked list are 12 K; if the index is max_index, that is, 20, the node size should be 8 K + 4 K * (MAX_INDEX-1) = 84 K, which is also the maximum number of "rule nodes" supported by Apache. However, this formula only applies to the index from 1 to max_index in the array, and is not suitable for index 0. Only when the size of the memory block applied by the user exceeds the 84k that the rule node can afford will it go to the linked list with an index of 0. The nodes in the linked list are generally larger than 84 K, and the size of each node is not exactly the same. In the following section, we refer to the linked list corresponding to index 1 to max_index as
Rule linked list", And each linked list is called"
Index n linked list", Corresponds to, the node in the Rule linked list is collectively referred to as"
Rule Node", Or"
Index n nodes", This is because their sizes have certain rules to follow, while the linked list corresponding to index 0 is called"
Index 0 linked list", The node is called"
Index 0 nodes". Based on the above description, we can provide the memory structure of the allocated Sub-Account 3.2. Figure 3.2 allocation of sub-memory structure in theory, the maximum node size of the Allocation Sub-should be 8 K + 4 K * (MAX_INDEX-1), but not necessarily so, if you have never allocated 8 K + 4 K * (MAX_INDEX-1) memory, the linked list corresponding to the max_index index is likely to be empty. In this case, the max_index variable is used to represent the actual maximum node in the allocation subnode. In addition, if the node is too large, it will occupy too much memory. In this case, it is necessary to return the node to the operating system and allocate the sub-account to use max_free_index as the minimum threshold for memory recovery. If the node is smaller than max_free_index, no processing is performed. Otherwise, the node must be released to the operating system. Current_free_index is .... In addition, mutex ensures mutex during multi-thread access, while the owner records the memory pool of the allocated sub-item. Apache provides several related functions for allocation subtasks. The function names and functions are briefly described in Table 3.1. Table 3.1 Sub-related functions are provided in Apache.
Allocate sub-operations |
Function Name |
Simple Function Description |
Create |
Apr_allocator_create |
Create a new Allocation Sub- |
Destroy |
Apr_allocator_destroy |
Destroys an existing Allocation Sub-Account. |
Space allocation |
Apr_allocator_alloc |
Call to allocate sub-allocated space |
Space release |
Apr_allocator_free |
Release the allocated space and return it to the allocated space. |
Other settings |
Apr_allocator_owner_setapr_allocator_owner_get |
Set and obtain the memory pool of the allocated Sub-Account |
Apr_allocator_max_free_setapr_allocator_set_max_free |
Set and obtain mutex variables in the Allocation Sub-body |
2.3.2 allocating sub-creation and destroying sub-creation are the prerequisites for all sub-operations. The so-called "No hair, no skin will be attached ". Assign sub-creation using function compute: apr_declare (apr_status_t) apr_allocator_create (parameters ** Allocator) {parameters * new_allocator; * Allocator = NULL; If (new_allocator = malloc (callback )) = NULL) return apr_enomem; memset (new_allocator, 0, sizeof_allocator_t); new_allocator-> max_free_index = partition; * Allocator = new_allocator; return apr_success;} suballocation It is very simple to create, and the function used is the most common malloc. The allocation size is sizeof_allocator_t, that is, the size of apr_align_default (sizeof (apr_allocator_t. Of course, the allocated space also includes an array of max_index pointer variables. Once the allocation is complete, the function initializes max_free_index to apr_allocator_max_free_unlimited. The value is actually 0, indicating that the Allocation Sub-nodes do not set a threshold for the size of idle nodes to be recycled. This means that the system will not recycle the nodes even if they. After creation, max_inde and current_free_index in the structure are all initialized to 0, which is actually implicitly initialized by the memset function. After creation, the function returns the created Allocation Sub-statement. However, the free array in the returned Allocation Sub-table does not contain any actual memory node linked list. The normal next step for sub-game use should be to initialize the structure members. The main initialization work is to set the threshold for returning system resources to the operating system max_free_index. We will see later that for memory allocated using malloc, if its size is smaller than the threshold value, these resources will not be released, but will be returned to the memory pool, when the memory pool itself is released, the memory is actually released to the operating system. If the memory size exceeds this threshold, the memory is directly released to the operating system. The threshold value is set by the callback function: apr_declare (void) Partition (apr_allocator_t * Allocator, apr_size_t in_size) {export max_free_index; apr_uint32_t size = (partition) in_size; max_free_index = apr_align (size, region)> boundary_index; Allocator-> current_free_index + = max_free_index; Allocator-> current_free_index-= Allocator-> max_free_index; Allocator-> Max_free_index = max_free_index; If (Allocator-> current_free_index> max_free_index) Allocator-> current_free_index = max_free_index;} the size in the parameter is adjusted and assigned to the distributed sub-structure max_free_index. In addition to max_free_index, another important member is current_free_index, which records the actual maximum memory block size in the current memory pool. Of course, its value cannot exceed the range of max_free_index. The corresponding action to the creation of the Allocation Sub-statement is the destruction of the Allocation Sub-statement. The destruction function apr_allocator_destroy is used. When the Allocation Sub-object is destroyed, we need to ensure that the following two aspects are correctly destroyed: (1) the Allocation Sub-object memory is released, this can directly call free processing (2). Because the embedded free array in the Allocation Sub-table points to an actual node linked list, you must ensure that these linked lists are correctly released. When releasing a linked list, you can traverse and release all the nodes in the linked list along the next step. Note the two release sequence problems before release. The correct order of release should be the earliest release of the linked list, followed by the release of the allocated sub-memory. In Apache, the release code is as follows: apr_declare (void) apr_allocator_destroy (apr_allocator_t * Allocator) {apr_uint32_t index; apr_memnode_t * node, ** ref; For (Index = 0; index <max_index; index ++) {ref = & Allocator-> free [Index]; while (node = * ref )! = NULL) {* ref = node-> next; free (node) ;}} free (Allocator );}
About the author
Zhang zhongqing currently focuses on embedded browsers, mobile middleware, and large-scale server design. The source code analysis of Apache is currently underway, and the Apache source code Panoramic Analysis is planned to be published in the next book. Apache articles are part of this book. If you are interested in Apache, contact us through flydish at sina.com.cn!
If you think this article is good, click the "recommended this article" link after this article !!