C 内存分配是如何在操作系统的最低级别进行的?

C 内存分配是如何在操作系统的最低级别进行的?,c,memory,memory-management,x86,operating-system,C,Memory,Memory Management,X86,Operating System,我试图弄清楚在操作系统中如何在最低级别分配内存。据我所知,操作系统只是对可用和不可用的内存进行簿记,而C编程语言将在最低级别进行分配 因此,第一个示例是我提出的一个简单内存分配系统,然后我从以下资源中获取了一个示例: 示例1: struct heap_elements { int start_address; int end_address; int size; int reservation; }; st

我试图弄清楚在操作系统中如何在最低级别分配内存。据我所知,操作系统只是对可用和不可用的内存进行簿记,而C编程语言将在最低级别进行分配

因此,第一个示例是我提出的一个简单内存分配系统,然后我从以下资源中获取了一个示例:

示例1:

    struct heap_elements {
        int start_address;
        int end_address;
        int size;
        int reservation;
    };

    struct heap_elements heap[25];

    // Write len copies of val into dest.
    void memset(int *dest, int val, int len)
    {
        int *temp = (int *)dest;
        for ( ; len != 0; len--) *temp++ = val;
    }

    /*
    * This function will take a source and destination and copy n amount
    * - of bytes from the source to the destination address. 
    */ 
    void memory_copy(unsigned char *source, unsigned char *destination, int bytes) {
        for (int i = 0; i < bytes; i++) {
            *(destination + i) = *(source + i);
        }
    }

    int find_memory_hole(int size) {

        for (int i = 0; i < total_elements; i++) {
            if (heap[i].reservation == 0) {
                if (heap[i].size >= size || heap[i].size == 0) {
                return i;
                }
            }
        }
        return -1;
    }

    int * malloc(int size) {   
        int hole = find_memory_hole(size);
        if (hole != -1) {
            if (heap[hole].start_address == 0) {
                heap[hole].start_address = ending_address;
                ending_address += size;
                heap[hole].end_address = ending_address;
                heap[hole].size = size;
                heap[hole].reservation = 1;
                kprintf("Starting address: %d\n", heap[hole].start_address);
                kprintf("Ending address: %d\n", heap[hole].end_address);
            } else {
                heap[hole].size = size;
                heap[hole].reservation = 1;
            }
            memset((int*)heap[hole].start_address, 0, size);
            return (int*)heap[hole].start_address;
        } else {
            kprintf("FREE SOME MEMORY~!\n");
            kprintf("WE NEED ROOM IN HERE~!\n");
            return 0;
        }
    }

    void heap_install() {
        total_elements = 25;
        starting_address = 0x100000;  // 1 - MB
        ending_address = 0x100000;    // 1 - MB
        max_memory_address = 0xEEE00000;  // 4 - GB

        for (int i = 0; i < total_elements; i++) {
            heap[i].start_address = 0;
            heap[i].end_address = 0;
            heap[i].size = 0;
            heap[i].reservation = 0;
        }

        return;
    }

    void free(void * pointer) {

        int memory_found = 0;
        kprintf("Address %d\n", &pointer);
        int memory_address = &pointer;

        for (int i = 0; i < total_elements; i++) {
            if (heap[i].start_address == memory_address) {
                heap[i].size = 0;
                heap[i].reservation = 0;
                memory_found = 1;
                break;
            }
        }

        if (memory_found == 0)
            kprintf("Memory could not bee free'd (NOT FOUND).\n");

        return;
    }
我希望:

char * ptr = malloc(5)

printf("The memory address for this pointer is at: %d\n", &ptr);
将接近0x100000内存地址,但不是。这是一些完全不同的地方,这就是为什么我认为我没有在物理上告诉char指针在内存中的位置,是C编程语言把它放在了不同的地方。我不知道我做错了什么,理解这一点应该不会这么难。另外,我在OSDev维基上搜索过,没有发现任何东西

我试图弄清楚如何在最低级别分配内存 在操作系统中。据我所知,操作系统 系统只是对可用内存进行簿记 而且不可用,这是C编程语言可以做到的 最低级别的分配

操作系统当然会记录哪些内存可用,哪些内存不可用,但用这些术语来描述会大大简化,我怀疑你对“内存”的含义的理解与最佳匹配不同

操作系统的虚拟内存管理子系统管理物理内存和其他存储资源(如基于磁盘的交换空间)如何映射到每个进程的虚拟地址空间,包括进程虚拟地址空间的多少以及哪些部分映射到可用内存。它服务于增加和减少进程可用虚拟内存的请求,以及创建内存映射(例如基于普通文件的映射)的显式请求

至于在用户空间程序中服务
malloc()
调用,您或多或少是正确的。程序通常以相当大的块从操作系统获取内存,这些块由
malloc()
free()
和朋友分割和管理。通常,这些细节只在进程填满已经可用的内存并且需要从内核请求更多时才涉及内核

但最低级别肯定在内核中。C库的内存管理功能只能使用操作系统分配给进程的内存

从这两个示例中,我期望从malloc()分配的内存 会有和我分配地址相同的起始地址,如果 这有道理吗?如果我知道内核的末尾是0x9000 标记,我想开始在1MB标记处分配内存。是的,我 知道我的内核在内存中的位置很奇怪,也不传统,但我 知道内存在超过1MB标记时是可用的

内核的内存视图与用户空间进程的内存视图不同。每个进程在其自己的虚拟地址空间中运行,而不了解它正在使用的物理地址

我试图弄清楚在操作系统中如何在最低级别分配内存

您的问题是,您没有看到操作系统如何分配内存。您将看到应用程序级内存分配

对于进程,操作系统仅以页为单位分配内存。进程通过调用将更多页面映射到进程地址(即使更多页面有效)的系统服务来获得更多内存

因为应用程序通常需要小于页面的内存分配(对于字符串之类的东西),所以经常使用堆管理函数。malloc和free很少(如果有的话)是操作系统服务。它们只是能够以小于一页的增量分配内存的函数


通常,对malloc的调用会导致函数尝试查找足够大的内存块以返回给调用方。如果这样一个块不可用,malloc将调用操作系统服务将页面映射到地址空间,以增加堆中的可用内存量,从而返回足够大的内存块。

,最低级别是a。这可能会有所帮助:我想在开始分页之前实现它。请注意
char*ptr=malloc(5);printf(“此指针的内存地址位于:%d\n”,&ptr)
不正确有两个原因:错误的格式说明符,它传递的是指针的位置,而不是指针的值。它应该是
printf(“%p\n”,(void*)ptr)
在某些系统中,您可能会“侥幸”使用错误的格式说明符,但通常情况下,如果
int*
占用8个字节而
int
占用4个字节,您将无法报告正确的地址。在POSIX操作系统上,
malloc
实现通常使用
mmap(MAP\u匿名)
和/或
brk()
/
sbrk()
从内核获取新的页面(glibc使用
brk
进行小的分配,使用
mmap
进行大的分配,因此它总是可以在
free
上将内存返回内核,而不是在用户可用空间列表上进行大量分配)。在Windows上,
VirtualAlloc()
kernel_end = 0x9000;
heap_starts = 0x100000;
heap_ends = 0x5B8D80;
char * ptr = malloc(5)

printf("The memory address for this pointer is at: %d\n", &ptr);