以下是一个非常非常简单的malloc()版本,并且似乎为我分配了一些空间,但除了没有free()之外我不检查我是否已超出分配的空间,怎么能我检查代码是否正确?
"C"专家会打击我的任何明显错误?
#include <stdio.h>
#include <unistd.h>
#define MAX_MEMORY 1024 * 1024 * 2 /* 2MB of memory */
void *stack = NULL; /* pointer to available stack */
void * memoryAlloc(size) {
if (stack == NULL)
stack = sbrk(MAX_MEMORY); /* give us system memory */
void *pointer;
pointer = (void *)stack + size; /* we always have space :) */
stack += size; /* move in stack forward as space allocated */
return pointer;
}
Run Code Online (Sandbox Code Playgroud) 我想从一个没有链接到标准C库的汇编程序动态分配内存.由于brk(2)和sbrk(2)在Mac OS X(10.6.2)上不可用,有哪些替代方案?
(我猜它涉及一个马赫调用,但似乎很少有文档)
因此,作为一项挑战,为了提高性能,我正在用汇编语言编写一个简单的服务器。我知道的唯一方法是通过系统调用。(通过 int 0x80)显然,我将需要比在汇编或加载时分配的内存更多的内存,所以我阅读并决定我想使用 sbrk(),主要是因为我不理解 mmap() :p
无论如何,Linux不为sbrk()提供中断,只为brk()提供中断。
那么...如何找到当前程序中断以使用brk()?我考虑过使用 getrlimit(),但我不知道如何获取资源(我猜的进程 ID)来传递给 getrlimit()。或者我应该找到其他方法来实现 sbrk() ?
我在各种操作系统中存在内存管理问题.
我的程序是一个服务器,它执行一些可能需要几GB内存的处理.之后,它会在等待几个小时直到另一个请求到达时释放大部分内存.
在AIX和Solaris上,我观察到以下行为,
当我释放内存时,内存不会返回给操作系统.进程使用的虚拟内存量总是增加 - 永不减少.对于物理内存也是如此,直到它的极限.因此,我们似乎也在睡眠模式下使用所有这些内存.
什么时候这个内存可以返回给操作系统?我该怎么做?
Linux是不同的:它似乎有时会返回内存,但我无法理解何时以及如何.例如,我有一个场景,其中请求之前的过程是100MB,然后是高峰时的700MB,并且在释放所有下降到600MB之后.我不明白 - 如果Linux为操作系统提供内存,为什么不是全部?
我读过高级Unix编程(以及其他一些书),Linux malloc()使用Linux系统调用sbrk()从操作系统请求内存.
我正在查看glibc malloc.c代码,我可以sbrk()在评论中看到很多提及,但在代码中没有直接引用.
sbrk()当malloc()从OS请求内存时,如何/在何处引用/使用?
(这可能是我对如何从C运行时库进行系统调用的一般误解.如果是这样,我会有兴趣知道它们是如何制作的?)
我知道程序中断是Linux操作系统为进程分配的最高虚拟内存地址,因此标记了堆的最高地址.您可以通过调用sbrk(0)来获取程序中断的地址.
当我创建以下简单程序时,每次运行时都会得到不同的结果:
#define _BSD_SOURCE
#include <stdio.h>
#include <unistd.h>
int main()
{
printf( "system break: %p\n", sbrk( 0 ) );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
例如,在我的电脑上:
$ ./sbrk
system break: 0x81fc000
$ ./sbrk
system break: 0x9bce000
$ ./sbrk
system break: 0x97a6000
Run Code Online (Sandbox Code Playgroud)
我的理解是堆直接分配在虚拟内存中的BSS部分之上 - 我想我期望它总是具有相同的初始值,就像这样一个简单的程序.是否存在一些随机化或程序中断最初定位的东西?如果没有,为什么每次运行程序时它都不同?
我已经彻底阅读了关于 sbrk() 的 linux 手册:
sbrk() 改变程序中断的位置,它定义了进程数据段的结束(即程序中断是未初始化数据段结束后的第一个位置)。
问题是: 当我调用 sbrk(1) 时,为什么它说我正在增加堆的大小?正如手册所说,我正在更改“数据段和 bss”的结束位置。那么,数据段和bss的大小应该增加多少,对吗?
我已经尝试在我的机器上使用sbrk(1)然后故意写出测试页面大小,这是4096字节.但是当我调用malloc(1)时,我在访问135152字节后获得了SEGV,这超过了一个页面大小.我知道malloc是库函数,它依赖于实现,但考虑到它最终会调用sbrk,为什么它会给出多个页面大小.谁能告诉我它的内部工作?
我的操作系统是ubuntu 14.04,我的架构是x86
更新:现在我想知道是不是因为malloc将地址返回到足以容纳我的数据的空闲列表块.但是该地址可能位于堆的中间,因此我可以继续写入,直到达到堆的上限.
我正在为STM32F7编写嵌入式软件,而我的libc是newlib-2.4.0.20160527。
我已经实现_sbrk()如下:
extern intptr_t g_bss_end; /* value after the last byte in .bss */
extern intptr_t g_msp_lim; /* stack buffer starts at this address */
intptr_t _sbrk(ptrdiff_t heap_incr)
{
static intptr_t heap_end = 0;
intptr_t prev_heap_end;
intptr_t new_heap_end;
if(heap_end == 0) {
heap_end = (intptr_t)&g_bss_end;
}
prev_heap_end = heap_end;
new_heap_end = prev_heap_end + heap_incr;
if(new_heap_end >= g_msp_lim) {
errno = ENOMEM;
return -1;
}
heap_end = new_heap_end;
return prev_heap_end;
}
Run Code Online (Sandbox Code Playgroud)
然后,当我执行以下操作时:
/* total capacity of my heap is …Run Code Online (Sandbox Code Playgroud) 我试图使用sbrk进行动态内存分配.但是,作为SPIM和MIPS的新来者,我无法这样做.我勾勒出一个粗略的代码.
.
data
var: .word 25
.text
main:
li $v0, 9
la $v0, var
lw $a0, var
syscall # DYNAMICALLY ALLOCATING MEMORY OF SIZE 4 BYTES AT ADDRESS OF VAR
sw $v0, var
li $v0, 10
syscall
Run Code Online (Sandbox Code Playgroud)