什么是POSIX?我已阅读维基百科的文章,每次遇到这个词时我都会阅读它.事实是,我从来没有真正理解它是什么.
任何人都可以通过解释"对POSIX的需求"向我解释一下吗?
在阅读有关汇编程序的文章时,我经常遇到人们在写文件时他们推送处理器的某个寄存器并稍后再次弹出它以恢复它之前的状态.
这个问题旨在填补关于该主题的良好免费信息的真空.
我相信一个好的答案将适合一个大的答案或至少在几个答案.
主要目标是为完整的初学者提供足够的信息,以便他们可以自己学习手册,并能够理解与分页相关的基本操作系统概念.
建议的指导方针:
相关问题以及为什么我认为它们不是愚蠢的:
x86页表如何工作?:标题与此问题几乎相同,但是正文询问与cr3和TLB相关的具体问题.那个问题是这个问题的一个子集.
x86虚拟化如何工作:正文仅询问源.
我正在努力理解这个sbrk()功能.
据我所知:
sbrk(0)返回中断的当前地址,不会增加它.
sbrk(size)以size字节为单位递增中断的地址,并返回中断的先前地址.
所以我创建了一些东西来测试它:
#include <unistd.h>
#include <stdio.h>
int main(void)
{
printf("sbrk(0) = %p\n", sbrk(0)); // should return value x
printf("sbrk(0) = %p\n", sbrk(0)); // should return value x
printf("sbrk(5) = %p\n", sbrk(5)); // should return value x
printf("sbrk(0) = %p\n", sbrk(0)); // should return value x + 5
}
Run Code Online (Sandbox Code Playgroud)
所以我期待看到如下结果:
sbrk(0) = 0x1677000 // x value
sbrk(0) = 0x1677000 // x value
sbrk(5) = 0x1677000 // x value
sbrk(0) = 0x1677005 // …Run Code Online (Sandbox Code Playgroud) 给定进程中堆的边界是什么?我理解这个问题可能没有简单的答案,所以我特别感兴趣的是以下答案:
malloc使用brk/ sbrk作为从OS声明内存的主要方式的典型实现。但是,它们还用于mmap获取大容量分配的块。使用brk代替确实有真正的好处mmap,还是仅仅是传统?将其与所有内容一起使用mmap是否会很好?
(注意:我在这里可以互换使用sbrk,brk因为它们是同一个Linux系统调用接口brk。)
作为参考,以下是一些描述glibc malloc的文档:
GNU C库参考手册:GNU分配器
https://www.gnu.org/software/libc/manual/html_node/The-GNU-Allocator.html
glibc Wiki:Malloc概述
https://sourceware.org/glibc/wiki/MallocInternals
这些文件所描述的是,它sbrk被用来声明一个小的分配的主要场所,mmap被用来声明一个次级的场所,mmap还被用来声明一个大对象(“比页面大得多”)的空间。
同时使用应用程序堆(带有sbrk),并mmap引入了一些其他不必要的复杂性:
分配的竞技场-主竞技场使用应用程序的堆。其他竞技场使用mmap堆。要将块映射到堆,您需要知道哪种情况适用。如果该位为0,则该块来自主区域和主堆。如果该位为1,则该块来自mmap的内存,并且可以从该块的地址计算出堆的位置。
[Glibc malloc源自ptmalloc,而ptmalloc则源自dlmalloc,后者始于1987年。]
该jemalloc手册页(http://jemalloc.net/jemalloc.3.html)有这样一段话:
传统上,分配器使用sbrk(2)获取内存,由于一些原因,该内存不是最佳的,原因包括竞争条件,增加的碎片以及人为限制最大可用内存。如果操作系统支持sbrk(2),则此分配器将按优先顺序使用mmap(2)和sbrk(2);否则,此分配器将使用mmap(2)和sbrk(2)。否则,仅使用mmap(2)。
因此,他们甚至在这里说这sbrk不是次优的,但是无论如何他们还是会使用它,即使他们已经为编写代码而烦恼,以至于没有它就可以工作。
[jemalloc的编写始于2005年。]
更新:更多地考虑这一点,关于“按优先顺序”的一点让我对询问保持了一致。为什么选择优先顺序?它们是否只是sbrk在mmap不支持(或缺少必要功能)的情况下用作备用,还是该进程可能进入可以使用sbrk但不能使用的状态mmap?我看一下他们的代码,看看是否能弄清楚它在做什么。
我之所以问是因为我正在用C实现垃圾回收系统,到目前为止,我看不到除之外的任何用途mmap。我想知道是否还有什么我想念的。
(就我而言,我还有另一个避免使用的原因brk,那就是malloc在某些时候可能需要使用。)
我在很多地方(MUSL邮件列表,MACOS论坛等)听说brk()和sbrk()不安全。这些地方中的许多要么根本不给出解释,要么给出非常模糊的解释。例如,此链接指出“这些功能从根本上被破坏了”,并继续说malloc和sbrk子系统被完全破坏了,它们破坏了堆,等等。
我的问题是:为什么会这样?如果malloc以这样的方式使用它来分配sbrk足够大的内存块,以平息或大大减少对进一步分配的需求,那么使用sbrk并且brk完全安全吗?
这是我sbrk和的实现brk:
sbrk:
#include <unistd.h>
#include <stddef.h>
void *sbrk(intptr_t inc)
{
intptr_t curbrk = syscall(SYS_brk, NULL);
if( inc == 0 ) goto ret;
if( curbrk < 0 ) return (void *)-1;
curbrk((void *)(curbrk+inc));
ret:
return (void *)curbrk;
}
Run Code Online (Sandbox Code Playgroud)
brk:
#include <unistd.h>
intptr_t brk(void *ptr)
{
if( (void *)syscall(SYS_brk, ptr) != ptr )
return -1;
else …Run Code Online (Sandbox Code Playgroud) 我们知道,当创建一个进程时,会为此进程分配一个堆栈.在linux中,堆栈的大小通常为8 Mb.我的问题是,从这个堆栈分配的位置?从用户空间还是从系统空间?
该malloc函数始终在堆上分配内存.然而,在研究维基百科上的Escape Analylis文章时,我发现作为一种优化,编译器可以将堆分配转换为堆栈分配.例如,如果它看到只使用分配的内存然后在函数内释放.
现在我的问题是,程序员有没有办法自己这样做.那是在堆栈上分配内存?我知道C99允许变量作为数组声明的大小给出,但是说程序员想要调整它的大小.可以吗?
malloc 是如何在内部实现的?如何在以下必要条件下实现 malloc
• Malloc 至少分配请求的字节数
• malloc 返回的指针指向一个已分配的空间(即程序可以成功读写的空间;)
• 对 malloc 的其他调用不会分配此空间或其任何部分,除非该指针之前已被释放。
• malloc 应该易于处理:malloc 必须尽快终止(它不应该是 NP-hard !;)
• Malloc 还应提供调整大小和释放功能。
该函数遵循以下签名: Void * malloc(size_t size);
我试图了解它是如何sbrk工作的.
这是我的小代码:
int main()
{
printf("end of the break : %p\n", sbrk(0));
printf("end of the break : %p\n", sbrk(10));
printf("new end of the break : %p\n\n", sbrk(0));
}
Run Code Online (Sandbox Code Playgroud)
这输出:
Run Code Online (Sandbox Code Playgroud)end of break : 0xaa6000 end of break : 0xac7000 new end of the break : 0xac700a
为什么前2个地址0xac7000 - 0xaa6000 = 21000而不是10?