提问人:uRSs 提问时间:11/10/2023 更新时间:11/10/2023 访问量:17
不明白 sbrk 是如何工作的,以及为什么我的结构无法访问
Don't understand how sbrk works and why my structure cannot be accessed
问:
// SPDX-License-Identifier: BSD-3-Clause
#include "osmem.h"
#include <sys/mman.h>
#include <sys/types.h>
#include <assert.h>
#include "block_meta.h"
#define MMAP_THRESHOLD (128 * 1024)
#define METADATA_SIZE (sizeof(struct block_meta))
// #define MAP_FAILED ((void *)-1)
int first_malloc = 0;
// struct block_meta {
// size_t size;
// int status;
// struct block_meta *prev;
// struct block_meta *next;
// };
void *global_base = NULL;
// goes through the list of blocks and finds the first free block that is big enough
struct block_meta *find_free_block(struct block_meta **last, size_t size) {
struct block_meta *current = global_base;
while (current && !(current->status && current->size >= size)) {
*last = current;
current = current->next;
}
return current;
}
// requests space from the OS using sbrk or mmap
struct block_meta *request_space(struct block_meta *last, size_t size) {
struct block_meta *block;
// if size < threshold, use sbrk
if (size < MMAP_THRESHOLD) {
// get the beginning of the new block of memory
block = sbrk(0);
// allocate more memory - reduce the number of sbrk system calls
if (first_malloc == 0)
{
first_malloc = 1;
block = sbrk(MMAP_THRESHOLD);
// ((void *)block == request);
// if (request == MAP_FAILED) return NULL;
}
else
{
void *request = sbrk(size + METADATA_SIZE);
assert((void *)block == request);
if (request == MAP_FAILED) return NULL;
if (last) {
last->next = block;
}
}
block->size = size;
block->next = NULL;
block->status = STATUS_ALLOC;
return block;
}
else
{
// use mmap
block = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// if mappping failed, return null
if (block == MAP_FAILED) return NULL;
// set the next pointer of the last block to point to the newly mapped block
if (last)
last->next = block;
// set the block's next to null
block->next = NULL;
block->status = STATUS_MAPPED;
block->size = size;
return block;
}
}
void *os_malloc(size_t size) {
struct block_meta *block;
// allign the size of the memory to the nearest bigger multiple of 8
int align = 8;
int offset = size + sizeof(struct block_meta);
int padding = -offset & (align - 1);
int alligned_size = (offset + (align - 1)) & -align;
// invalid size
if (size <= 0) return NULL;
if (!global_base)
{
// First call.
// request space
block = request_space(NULL, size);
// request failed
if (!block) return NULL;
// set the new head of the list
global_base = block;
// block->status = STATUS_ALLOC;
block->size = alligned_size;
block->next = NULL;
}
else
{
struct block_meta *last = global_base;
block = find_free_block(&last, size);
if (!block)
{
// Failed to find free block.
block = request_space(last, size);
// failed to request space
if (!block) return NULL;
}
else
{ // Found free block
// TODO: consider splitting block here.
block->status = STATUS_ALLOC;
}
}
return (block + 1);
}
// returns the pointer to the allocated data, not the meta data
struct block_meta *get_block_ptr(void *ptr)
{
return (struct block_meta*)ptr - 1;
}
void os_free(void *ptr)
{
if (!ptr)
return;
struct block_meta *block_ptr = get_block_ptr(ptr);
if (block_ptr->status == STATUS_ALLOC)
{
block_ptr->status = STATUS_FREE;
}
else
{
block_ptr->status = STATUS_FREE;
munmap(block_ptr, block_ptr->size);
}
}
void *os_calloc(size_t nmemb, size_t size) {
/* TODO: Implement os_calloc */
return NULL;
}
void *os_realloc(void *ptr, size_t size) {
/* TODO: Implement os_realloc */
return NULL;
}
我正在尝试通过我自己的 malloc 实现来了解 sbrk 和 mmap 是如何工作的。当我尝试使用 sbrk 路由遍历第一个 malloc 时,我正在预先分配更多空间,以尽量减少以后对 sbrk 函数的调用次数。这也需要更多的工作,但现在我不明白为什么当我尝试访问 block->size 或 block->next 时,我会出现 seg 错误。我认为我对 sbrk 的理解完全是垃圾:)
答: 暂无答案
评论