(C) How to write / read from the memory address returned by mmap?

I read some pages on how to ask questions, so I hope this is consistent with the standard.

Our professor wants us to create a custom malloc and a free one that uses buddy distribution. Instead of messing around with a bunch, he wants us to just use mmap to request 1 gigabyte of space from the OS:

MAX_MEM = 1 << 30.
void * base = mmap(NULL, MAX_MEM, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);

Each piece of memory should have a header, and if the memory is empty, it indicates the next and previous free fragments through a linked list.

I don’t know how to say: "I want to put this specific data in this particular place." I would suggest that there will be a free fragment in memory:

[Occupancy (1 bit)][Size (7 bits)][prev pointer (8 bytes)][next pointer (8bytes)][junk]

So, let's say that all 1 GiB is free. Pseudocode:

Occupancy = 0; // 0 if empty, 1 if allocated
Size = 0011110; // where size in bytes = 2^Size
next = NULL;
prev = NULL; //note that these are part of a struct called mallocList

, ?

,

int MAX_MEM = 1 << 30;
base = mmap(NULL, MAX_MEM, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);

*((unsigned char*) base) = 0x1E;
struct mallocList* temp;
temp->prev = NULL;
temp->next = NULL;
void* tempaddr = base + 1;

*((struct mallocList*) tempaddr) = *temp;

munmap(base, 1 <<30);

, , ,

printf("%c", *base); //line 37
struct mallocList* two;
two->prev = NULL;
two->next = NULL;
tempaddr->next = *two; //line 41

,

3.c:37: warning: dereferencingvoid *’ pointer
3.c:37: error: invalid use of void expression
3.c:41: warning: dereferencingvoid *’ pointer
3.c:41: error: request for membernextin something not a structure or union

, - , , .

mymalloc.h:

void *my_buddy_malloc(int size);
void my_free(void *ptr);

struct mallocList
{
  struct mallocList *prev;
  struct mallocList *next;

} mallocList;
+4
1

: void*. char* struct yourstruct * struct p->field.

/* You need to tell gcc to pack the struct without padding,
 * because you want the pointers stored starting with the second byte,     i.e. unaligned.
 * That actually fine in *this* case, since they won't cross a cache-line boundary.
 * They'll be at the beginning of a page, from mmap, and thus the beginning of a cache line.  
 * Modern CPUs are fast at handling misaligned loads within a cache line.
 */

struct __attribute__ ((__packed__)) mem_block {
    unsigned int occupied:1;
    unsigned int size:7;   // bitfields.  Not necessarily a good idea.  Just using a signed int yourself might be better.  positive for allocated, negative for free.
    struct mallocList { // nested definition.  You can do this differently
        struct mallocList *prev, *next;
    } pointers;
};  // don't need the type-name here.  That would declare a variable of the struct type.


int MAX_MEM = 1 << 30;
void *base = mmap(NULL, MAX_MEM, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);

char *cp = base;
cp[0] = size << 1 | 1;  // pack the size and occupied bits into a byte
struct mallocList *mlp = (struct mallocList*)(cp+1);  // This avoids needing a compiler-specific way to pack your struct.

// or
struct mem_block *mbp = base;
mbp->occupied = 1;
mbp->size=whatever;
mbp->pointers.prev = NULL;
mbp->pointers.next = NULL;

, , .

0

Source: https://habr.com/ru/post/1615933/


All Articles