Malloc / free功能管理内存池。这些功能通常不是操作系统服务。
那个游泳池是怎么创建的?
在大多数系统上,malloc调用操作系统服务将页面映射到进程地址空间以创建和扩展内存池。如果调用malloc,并且没有可用的内存,则大多数实现将调用系统服务来映射更多内存并扩展池。
malloc实现需要维护数据结构,以跟踪池中的内存是空闲的以及已分配的内容。这可以通过许多不同的方式完成。程序员选择最适合他们的malloc / free组合并将其链接到他们的应用程序中并不罕见。
所以,是的,通常是操作系统参与。
但是你问他们是否可以在没有操作系统的情况下实现它们。
假设你做了:
static char pool [POOLSIZE] ;
在你的malloc实现中。然后,您不需要系统服务来在执行期间创建池。另一方面,您的游泳池有固定的大小。
一般来说:如果我们将运行时定义为之间的时刻,则不,或者至少不在运行时 main() 进入和返回。
main()
假设您实现了在固定大小的池上运行的malloc:
static char pool[MALLOC_POOL_SIZE]; void *malloc(size_t size) { … } void free(void *block) { … }
然后,在托管和非托管实现上,您都可以使用动态内存分配。在托管实现上,二进制加载器将确保在后面映射内存 pool 。在非托管实现上,链接器将在可用RAM中预定位池,如果池太大,链接将失败。
pool
所以不,一般来说,一旦你的代码运行就不需要操作系统,但是需要操作系统来让你的代码首先运行(如果有操作系统)。
当然,“不需要”意味着没有必要,但不排除OS支持特定C运行时库中的动态内存分配。在大多数托管运行时中, malloc 使用通过调用相关OS API动态扩展(也可能是缩小)的池。在经典的Unix上,扩展将通过 brk 系统调用。
malloc
brk
malloc() 和 free() 不需要OS支持。它们可以(通常是!)在裸机系统上实现。例如,Arduino库使用 malloc() 和 free() 管理字符串。
malloc()
free()
在托管实现中(即,在操作系统上运行的应用程序), malloc() 和 free() 通常会使用操作系统服务来分配新的内存“ - 通常一次只有几兆字节” - 并且在未使用时将这些存储器返回给操作系统。通过将这些内存块切割成应用程序所需的大小来处理较小的分配。这允许在没有系统调用开销的情况下管理小分配。
在一个非主机实现(如裸机系统)中,应用程序已经可以访问系统中存在的所有内存,并且可以根据需要分配该内存的块。
在较低级别:托管和非托管实现 malloc() 通常通过将每个已分配或未分配的内存块视为链接列表中的条目来工作。这通常是通过在每次分配开始之前立即存储结构来实现的,例如,
struct malloc_block { struct malloc_block *prev, *next; size_t size; ... char allocation[]; };
并返回一个指针 allocation 作为返回值 malloc() 。功能如 realloc() 和 free() 可以通过从指向分配的指针中减去结构的大小来检索结构。
allocation
realloc()