c - 如何确定工艺尺寸?

标签 c operating-system

关闭。这个问题是off-topic .它目前不接受答案。












想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。

9年前关闭。




Improve this question




我对这些概念很陌生,但我想问大家一个我认为非常基本的问题,但我很困惑,所以我问这个问题。
问题是...
操作系统如何确定进程的大小?
先说清楚,假设我写了一个C程序,我想知道它要占用多少内存,我如何确定它?其次我知道一个进程有很多部分,比如代码部分,数据部分,BSS。现在这些的大小是预先确定的吗?其次是如何确定堆栈和堆的大小。在计算进程的总大小时,堆栈和堆的大小是否也很重要。

我们再次说,当我们加载程序时,会为进程分配一个地址空间(这是由基址和限制寄存器完成并由 MMU 控制,我猜)并且当进程尝试访问不在其内部的内存位置时地址空间我们得到段错误。进程如何访问不在其地址空间中的内存。根据我的理解,当发生某些缓冲区溢出时,地址就会损坏。现在,当进程想要访问损坏的位置时,我们就会遇到段错误。是否有任何其他方式违反地址。

第三,为什么栈向下增长而堆向上。这个过程是否与所有操作系统相同。它如何影响性能。为什么我们不能以其他方式拥有它?

如果我在任何陈述中错了,请纠正我。

谢谢
索拉博

最佳答案

当一个进程启动时,它会获得自己的虚拟地址空间。虚拟地址空间的大小取决于您的操作系统。通常,32 位进程获得 4 GiB(4 千兆二进制)地址,64 位进程获得 18 个 EiB(18 个 exa 二进制)地址。

您不能以任何方式访问任何未映射到您的虚拟地址空间的任何内容,因为根据定义,任何未映射到那里的内容都没有适合您的地址。您可能会尝试访问当前未映射到任何内容的虚拟地址空间区域,在这种情况下,您会收到段错误异常。

在任何给定时间,并非所有地址空间都映射到某些内容。也不是所有的都可以被映射(可以映射多少取决于处理器和操作系统)。在当前一代的英特尔处理器上,最多可以映射 256 TiB 的地址空间。请注意,操作系统可以进一步限制。例如,对于 32 位进程(最多具有 4 GiB 地址),Windows 默认为系统保留 2 GiB,为应用程序保留 2 GiB(但有一种方法可以使系统为 1 GiB,应用程序为 3 GiB)。

在应用程序运行时,使用了多少地址空间以及映射了多少地址空间。操作系统特定工具可让您监控当前为正在运行的应用程序分配的内存和虚拟地址空间。

代码段、数据段、BSS 等是指链接器创建的可执行文件的不同区域的术语。通常,代码与静态不可变数据分开,静态不可变数据与静态分配但可变数据分开。堆栈和堆与上述所有内容都是分开的。它们的大小由编译器和链接器计算。请注意,每个二进制文件都有自己的部分,因此任何动态链接的库都将分别映射到地址空间中,每个文件都有自己的部分映射到某处。但是,堆和堆栈不是二进制镜像的一部分,通常每个进程只有一个堆栈和一个堆。

堆栈(至少是初始堆栈)的大小通常是固定的。编译器和/或链接器通常有一些标志,可用于在运行时设置所需的堆栈大小。堆栈通常“向后增长”,因为这就是处理器堆栈指令的工作方式。让堆栈朝一个方向增长,其余的朝另一个方向增长,在您希望两者都不受限制但不知道每个可以增长多少的情况下,可以更轻松地组织内存。

一般来说,堆是指进程启动时没有预先分配的任何东西。在最低级别,有几个与堆管理相关的逻辑操作(并非所有操作都如我在此处描述的那样在所有操作系统中实现)。

虽然地址空间是固定的,但一些操作系统会跟踪进程当前回收了它的哪些部分。即使情况并非如此,流程本身也需要对其进行跟踪。因此,最低级别的操作是实际决定要使用地址空间的某个区域。

第二个低级操作是指示操作系统将该区域映射到某物。这一般可以

  • 一些不可交换的内存
  • 可交换并映射到系统交换文件的内存
  • 可交换并映射到其他文件的内存
  • 可交换并以只读模式映射到其他文件的内存
  • 另一个虚拟地址区域映射到
  • 的相同映射
  • 与另一个虚拟地址区域映射到的映射相同,但处于只读模式
  • 与另一个虚拟地址区域映射到的映射相同,但处于写入时复制模式,复制的数据映射到默认交换文件

  • 我可能忘记了其他组合,但这些是主要的组合。

    当然,使用的总空间实际上取决于您如何定义它。当前使用的 RAM 与当前映射的地址空间不同。但正如我上面写的,操作系统相关工具应该让您了解当前正在发生的事情。

    关于c - 如何确定工艺尺寸?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12490929/

    相关文章:

    linux - 如何在 linux cat 命令中一起处理单引号/撇号和空格?

    c - fork() 和 ~fork() 有什么区别

    在linux机器上调用系统调用

    c - 如何从 C 函数调用 Objective-C 函数

    c++ - 字符串变量中使用的宏定义

    c - 使用c程序清空回收站

    java - 动态确定操作系统

    c - 子进程中的dup2是否更改了父进程中的fd表?

    java - 将函数的前 2 个参数之外的所有参数传递给另一个函数

    go - 如何在 golang 中打印到 stdout 的同时将 stdout 保存到字符串?