如何与其他 processes/threads 共享内存布局?
How is memory layout shared with other processes/threads?
我目前正在学习 C 中的内存布局。目前我知道 C 程序内存中存在几个部分:text
、data
、bss
、heap
和 stack
。他们还说 heap
与程序以外的其他东西共享。
我的问题是这些。
heap
的分享对象到底是什么?一个消息来源指出 堆必须始终被释放,以使其可用于 其他进程 而另一个消息来源说 堆区域是由进程中的所有线程、共享库和动态加载模块共享。 如果它不与其他进程共享,我真的必须在我的程序中释放它吗是运行(不是在它的末尾)?
- 一些来源还为命令行参数和环境变量挑出了高地址(第六部分)。这算不算另外一层,是程序内存的一部分?
- 其他部分是否与程序以外的任何其他内容共享?
- 在所有进程都使用 RAM 的意义上,堆与其他进程共享。您使用的越多,其他程序可用的就越少。在您自己的程序中与其他线程共享堆意味着您的所有线程实际上都看到并访问同一个堆(相同的虚拟地址 space、相同的实际 RAM,运气好的话还有相同的缓存)。
- 没有
text
可以与其他进程共享。现在它被标记为只读,所以让多个进程共享 text
是有意义的。在实践中,这意味着如果您已经 运行ning top
并且您 运行 另一个实例,那么再次加载 text
部分是没有意义的。这会浪费时间和物理 RAM。如果 OS 足够聪明,它可以将那些 RAM 页面映射到两个 top
实例的虚拟地址 space,从而节省时间和 space.
官方方面:
术语线程、进程、文本部分、数据section、bss、heap和stack连C语言都没有定义标准,每个平台都可以自由地实现这些组件,但是“它可能喜欢”。
线程和进程通常在操作系统层实现,而所有不同的内存部分通常在编译器层实现。
实用方面:
对于每个给定的进程,所有这些内存部分(文本部分、数据部分、bss、堆和堆栈)都由该进程的所有线程共享。
因此,程序员有责任确保从不同线程访问这些内存部分时互斥。
通常,这是通过信号量、互斥锁和消息队列等同步实用程序实现的。
在进程之间,由操作系统负责确保互斥。
通常,这是通过虚拟内存抽象实现的,其中每个进程在其自己的逻辑地址 space 内运行,每个逻辑地址 space 映射到不同的物理地址 space.
免责声明:有人会说每个线程都有自己的堆栈,但从技术上讲,这些堆栈通常是连续分配在进程的堆栈上的,通常没有人阻止一个线程访问其他线程的堆栈线程,无论是有意还是无意(又名 堆栈溢出)。
heap
是 每个进程 内存:每个进程都有自己的堆,仅在同一个 进程中共享 space(如您所说,在进程 线程 之间)。你为什么要释放它?不正确地将 space 提供给其他进程(至少在现代 OS 中,当进程死亡时进程内存由 OS 回收),但要防止进程内存中的堆耗尽: 在 C 中,如果您不释放您使用的堆内存区域,即使它们不再被使用,它们也将始终被视为繁忙。因此,为防止出现意外错误,最好在不再需要时释放堆中的内存。
- 在 C 程序中,命令行变量作为 main 的 函数变量 存储在堆栈中。发生的情况是,通常堆栈分配在进程内存的最高部分,映射到高地址(这可能是某些来源指出您写的内容的原因)。但是,一般来说,是没有第六内存区的。
- 正如其他人所说,
text
区域可以被进程共享。该区域通常包含二进制代码,对于共享相同二进制文件的不同进程来说是相同的。出于性能原因,OS 可以允许共享此类内存区域,(例如当您 fork
一个子进程时考虑)。
我目前正在学习 C 中的内存布局。目前我知道 C 程序内存中存在几个部分:text
、data
、bss
、heap
和 stack
。他们还说 heap
与程序以外的其他东西共享。
我的问题是这些。
heap
的分享对象到底是什么?一个消息来源指出 堆必须始终被释放,以使其可用于 其他进程 而另一个消息来源说 堆区域是由进程中的所有线程、共享库和动态加载模块共享。 如果它不与其他进程共享,我真的必须在我的程序中释放它吗是运行(不是在它的末尾)?- 一些来源还为命令行参数和环境变量挑出了高地址(第六部分)。这算不算另外一层,是程序内存的一部分?
- 其他部分是否与程序以外的任何其他内容共享?
- 在所有进程都使用 RAM 的意义上,堆与其他进程共享。您使用的越多,其他程序可用的就越少。在您自己的程序中与其他线程共享堆意味着您的所有线程实际上都看到并访问同一个堆(相同的虚拟地址 space、相同的实际 RAM,运气好的话还有相同的缓存)。
- 没有
text
可以与其他进程共享。现在它被标记为只读,所以让多个进程共享text
是有意义的。在实践中,这意味着如果您已经 运行ningtop
并且您 运行 另一个实例,那么再次加载text
部分是没有意义的。这会浪费时间和物理 RAM。如果 OS 足够聪明,它可以将那些 RAM 页面映射到两个top
实例的虚拟地址 space,从而节省时间和 space.
官方方面:
术语线程、进程、文本部分、数据section、bss、heap和stack连C语言都没有定义标准,每个平台都可以自由地实现这些组件,但是“它可能喜欢”。
线程和进程通常在操作系统层实现,而所有不同的内存部分通常在编译器层实现。
实用方面:
对于每个给定的进程,所有这些内存部分(文本部分、数据部分、bss、堆和堆栈)都由该进程的所有线程共享。
因此,程序员有责任确保从不同线程访问这些内存部分时互斥。
通常,这是通过信号量、互斥锁和消息队列等同步实用程序实现的。
在进程之间,由操作系统负责确保互斥。
通常,这是通过虚拟内存抽象实现的,其中每个进程在其自己的逻辑地址 space 内运行,每个逻辑地址 space 映射到不同的物理地址 space.
免责声明:有人会说每个线程都有自己的堆栈,但从技术上讲,这些堆栈通常是连续分配在进程的堆栈上的,通常没有人阻止一个线程访问其他线程的堆栈线程,无论是有意还是无意(又名 堆栈溢出)。
heap
是 每个进程 内存:每个进程都有自己的堆,仅在同一个 进程中共享 space(如您所说,在进程 线程 之间)。你为什么要释放它?不正确地将 space 提供给其他进程(至少在现代 OS 中,当进程死亡时进程内存由 OS 回收),但要防止进程内存中的堆耗尽: 在 C 中,如果您不释放您使用的堆内存区域,即使它们不再被使用,它们也将始终被视为繁忙。因此,为防止出现意外错误,最好在不再需要时释放堆中的内存。- 在 C 程序中,命令行变量作为 main 的 函数变量 存储在堆栈中。发生的情况是,通常堆栈分配在进程内存的最高部分,映射到高地址(这可能是某些来源指出您写的内容的原因)。但是,一般来说,是没有第六内存区的。
- 正如其他人所说,
text
区域可以被进程共享。该区域通常包含二进制代码,对于共享相同二进制文件的不同进程来说是相同的。出于性能原因,OS 可以允许共享此类内存区域,(例如当您fork
一个子进程时考虑)。