brk()系统调用做什么? [英] What does the brk() system call do?

查看:423
本文介绍了brk()系统调用做什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Linux程序员手册:

According to Linux programmers manual:

brk()和sbrk()更改程序中断的位置, 定义流程数据段的结尾.

brk() and sbrk() change the location of the program break, which defines the end of the process's data segment.

这里的数据段是什么意思?它仅仅是数据段还是数据,BSS和堆的组合?

What does the data segment mean over here? Is it just the data segment or data, BSS, and heap combined?

根据Wiki:

有时,数据,BSS和堆区域统称为数据段".

Sometimes the data, BSS, and heap areas are collectively referred to as the "data segment".

我没有理由仅更改数据段的大小.如果是数据,请 BSS 并进行集体堆放,则有意义的是,堆放会获得更多空间.

I see no reason for changing the size of just the data segment. If it is data, BSS and heap collectively then it makes sense as heap will get more space.

这带给我第二个问题.到目前为止,在我读过的所有文章中,作者都​​说堆是向上增长的,而堆是向下增长的.但是他们没有解释的是,当堆占据了堆和栈之间的所有空间时会发生什么?

Which brings me to my second question. In all the articles I read so far, author says that heap grows upward and stack grows downward. But what they do not explain is what happens when heap occupies all the space between heap and stack?

推荐答案

在您发布的图中,"break"(由brksbrk操纵的地址)是堆顶部的虚线

In the diagram you posted, the "break"—the address manipulated by brk and sbrk—is the dotted line at the top of the heap.

您已经阅读的文档将其描述为数据段"的结尾,因为在传统的(预共享库,mmap之前的)Unix中,数据段与堆是连续的.在程序启动之前,内核将从地址零(实际上比地址零稍高一点,以便NULL指针真正不指向任何内容)开始将文本"和数据"块加载到RAM中,并将中断地址设置为数据段的末尾.如图所示,对malloc的第一次调用将使用sbrk移动分手并在数据段顶部和新的,更高的中断地址之间的之间创建堆. ,随后使用malloc可以根据需要使用它来使堆变大.

The documentation you've read describes this as the end of the "data segment" because in traditional (pre-shared-libraries, pre-mmap) Unix the data segment was continuous with the heap; before program start, the kernel would load the "text" and "data" blocks into RAM starting at address zero (actually a little above address zero, so that the NULL pointer genuinely didn't point to anything) and set the break address to the end of the data segment. The first call to malloc would then use sbrk to move the break up and create the heap in between the top of the data segment and the new, higher break address, as shown in the diagram, and subsequent use of malloc would use it to make the heap bigger as necessary.

同时,堆栈从内存的顶部开始,然后向下扩展.堆栈不需要显式的系统调用即可使其变大.它要么开始时分配了尽可能多的RAM(这是传统方法),要么在堆栈下方有一个保留地址区域,当内核注意到尝试写入该区域时,内核会自动向其分配RAM (这是现代方法).无论哪种方式,在地址空间的底部可能有也可能没有保护"区域,可用于堆栈.如果存在该区域(所有现代系统都这样做),则将永久性地将其映射;如果 堆栈或堆试图长入其中,则会出现分段错误.但是,传统上,内核不尝试强制执行边界.堆栈可能会增长到堆中,或者堆可能会增长到堆栈中,并且它们以任何一种方式乱写彼此的数据,并且程序将崩溃.如果您很幸运,它将立即崩溃.

Meantime, the stack starts at the top of memory and grows down. The stack doesn't need explicit system calls to make it bigger; either it starts off with as much RAM allocated to it as it can ever have (this was the traditional approach) or there is a region of reserved addresses below the stack, to which the kernel automatically allocates RAM when it notices an attempt to write there (this is the modern approach). Either way, there may or may not be a "guard" region at the bottom of the address space that can be used for stack. If this region exists (all modern systems do this) it is permanently unmapped; if either the stack or the heap tries to grow into it, you get a segmentation fault. Traditionally, though, the kernel made no attempt to enforce a boundary; the stack could grow into the heap, or the heap could grow into the stack, and either way they would scribble over each other's data and the program would crash. If you were very lucky it would crash immediately.

我不确定此图中512GB的数字来自何处.它意味着一个64位的虚拟地址空间,这与您在那里拥有的非常简单的内存映射不一致.实际的64位地址空间看起来像这样:

I'm not sure where the number 512GB in this diagram comes from. It implies a 64-bit virtual address space, which is inconsistent with the very simple memory map you have there. A real 64-bit address space looks more like this:

              Legend:  t: text, d: data, b: BSS

这并不是遥不可及的,它不应该被解释为任何给定OS的工作方式(我画了它之后,我发现Linux实际上使可执行文件比我认为的更接近地址零,并且共享库的地址令人惊讶地高).此图的黑色区域是未映射的-任何访问都会立即导致段错误-相对于灰色区域,它们是硕大的.浅灰色区域是程序及其共享库(可以有数十个共享库);每个都有一个独立文本和数据段(和"bss"段,它也包含全局数据,但被初始化为全零位,而不是占用磁盘上的可执行文件或库中的空间).堆不再必须与可执行文件的数据段连续-我是用这种方式绘制的,但是看起来至少Linux并没有这样做.堆栈不再固定在虚拟地址空间的顶部,并且堆栈与堆栈之间的距离是如此之大,您不必担心会跨越它.

This is not remotely to scale, and it shouldn't be interpreted as exactly how any given OS does stuff (after I drew it I discovered that Linux actually puts the executable much closer to address zero than I thought it did, and the shared libraries at surprisingly high addresses). The black regions of this diagram are unmapped -- any access causes an immediate segfault -- and they are gigantic relative to the gray areas. The light-gray regions are the program and its shared libraries (there can be dozens of shared libraries); each has an independent text and data segment (and "bss" segment, which also contains global data but is initialized to all-bits-zero rather than taking up space in the executable or library on disk). The heap is no longer necessarily continous with the executable's data segment -- I drew it that way, but it looks like Linux, at least, doesn't do that. The stack is no longer pegged to the top of the virtual address space, and the distance between the heap and the stack is so enormous that you don't have to worry about crossing it.

中断仍然是堆的上限.但是,我没有显示的是,可能会有数十个独立的内存分配以mmap而不是brk的形式出现在黑色的某个地方. (操作系统将尝试将它们远离brk区域,以免它们发生冲突.)

The break is still the upper limit of the heap. However, what I didn't show is that there could be dozens of independent allocations of memory off there in the black somewhere, made with mmap instead of brk. (The OS will try to keep these far away from the brk area so they don't collide.)

这篇关于brk()系统调用做什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆