Implementation of malloc

Source: Internet
Author: User

http://blog.jobbole.com/75656/

Prototype: void* malloc (size_t size);

function: Allocate a contiguous amount of available memory in the system.

Requirements:

    • malloc allocates memory size at least the number of bytes specified by the size parameter
    • The return value of malloc is a pointer to the starting address of an available memory
    • Multiple calls to malloc are assigned an address that cannot have overlapping portions unless the address assigned to a malloc is freed
    • malloc should complete memory allocations as soon as possible and return (cannot use Np-hard's memory allocation algorithm)
    • Memory resizing and memory release functions (i.e. realloc and free) should be implemented when malloc is implemented

Background knowledge:

In general, the memory requested by malloc is primarily allocated from the heap area (this article does not consider the case of requesting large chunks of memory through mmap).

The virtual memory address space that the process faces can only be used if it is mapped to a physical memory address by page. Limited by physical storage capacity, the entire heap virtual memory space may not all be mapped to actual physical memory. Linux's management of the heap is as follows:

Linux maintains a break pointer that points to an address in the heap space. The address space from the heap start address to the break is mapped so that it can be accessed by the process, and from break up, the address space is unmapped, and the program will error if the space is accessed.

To increase the actual available heap size of a process, you need to move the break pointer to a high address. Linux uses the BRK and SBRK system calls to manipulate the break pointer. The prototypes for the two system calls are as follows:

int brk (void *addr);

void *sbrk (intptr_t increment);

  BRK Sets the break pointer directly to an address, and SBRK will break to move the increment specified by increment from the current position. BRK returns 0 on successful execution, otherwise returns 1 and sets errno to the address pointed to before the break moves when Enomem;sbrk succeeds, otherwise returns (void *)-1.

A little trick is that if you set increment to 0, you can get the address of the current break.

It is also important to note that because Linux is memory-mapped by page, if break is set to not align by page size, the system will actually map a full page at the end, so that the actual mapped memory space is larger than the place where break points. But it is dangerous to use the address after break (although there may be a small block of available memory after break).

Implementation :

Data:

The heap memory space is organized in chunks (blocks), each of which consists of a meta-area and a data area, where meta-data blocks are recorded (data area size, idle flag bits, pointers, and so on), and the data area is a truly allocated area of memory. And the first byte address of the data area is the address returned by malloc.

typedefstructS_block *T_block;structS_block {size_t size; /*Data area size*/T_block Next;/*Pointer to next block*/    int  Free;/*whether it is a free block*/    intPadding/*padding 4 bytes to ensure that the meta block length is a multiple of 8*/    Chardata[1];/*This is a virtual field that represents the first byte of the data block, and the length should not be counted in the meta*/};

Find the right block in the block chain. There are generally two search algorithms:

    • First fit: Starting from the beginning, use a block of size larger than the one that is called this allocation
    • Best fit: From the beginning, traverse all blocks, using blocks with a data area size greater than size and the smallest difference for this allocated block

The two methods are different, best fit has a high memory usage (payload), and first fit has better operational efficiency.

First Fit algorithm:

T_block Find_block (T_block * Last, size_t size) {    = first_block;      while (b &&!) (b-> free && b->size >= size)) {        *last = b;         = B->next;    }     return b;}

Find_block starts with Frist_block, finds the first qualifying block and returns the block start address, if this returns null if it is not found. This will update a pointer called last when traversing, which always points to the currently traversed block. This is to open a new block if the appropriate block is not found, and it will be in the next section.

Open up a new block

If the existing block does not meet the size requirement, then a new block will be created at the end of the list. The key here is how to create a struct using only sbrk:

#defineBlock_size 24/* Due to the existence of the virtual data field, sizeof does not correctly calculate the meta length, which is set manually */T_block extend_heap (T_block last, size_t s) {T_block B; b= SBRK (0); if(SBRK (block_size + s) = = (void*)-1)        returnNULL; b->size =s; b->next =NULL; if(last)->next =b; b- Free=0; returnb;}
Split block

One of the fatal drawbacks of first fit is that it is possible to make a small size occupy a large block, and in order to improve payload, it should be split into a new block if the remaining data area is large enough.

void Split_block (T_block B, size_t s) {    new;     new = B->data + s;     new->size = b->size-s- block_size;     new->next = b->next;     New--free1;    b->size = s;    bnew;}

Implementation of malloc

With the code above, we can use them to integrate into a simple but initially available malloc. Note that first we want to define the header First_block of the Block list, initialize to NULL, and we need the remaining space at least block_size + 8 to perform the split operation.

Since we want the data area allocated by malloc to be 8-byte aligned, we need to resize the size to a multiple of the smallest 8 of the size if the size is not a multiple of 8:

size_t Align8 (size_t s) {if(S &0x7==0)        returns; return(S >>3) +1) <<3;}#defineBlock_size 24void*first_block=NULL;/*Other functions ...*/ void*malloc(size_t size) {T_block B, last;    size_t S; /*Snap To address*/s=align8 (size); if(first_block) {/*Find the right block*/ Last=First_block; b= Find_block (&Last , s); if(b) {/*if it can, then split*/            if((b->size-s) >= (block_size +8) ) Split_block (b, s); b- Free=0; } Else {            /*without the right block, open up a new*/b=Extend_heap (last, s); if(!b)returnNULL; }    } Else{b=Extend_heap (NULL, s); if(!b)returnNULL; First_block=b; }    returnB->data;}

calloc:

    1. malloc section of Memory
    2. Place data area content at 0

Since our data area is aligned at 8 bytes, we can set 0 per 8 bytes, rather than one byte setting, in order to improve efficiency. We can do this by creating a new size_t pointer that forces the memory area to be considered the size_t type.

void*calloc(size_t number, size_t size) {size_t*New;    size_t S8, I; New=malloc(Number *size); if(New) {S8= ALIGN8 (number * size) >>3;  for(i =0; i < S8; i++)            New[I] =0; }    return New;}

Implementation of malloc

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.