【问题标题】:maximum size of bss and databss 和数据的最大大小
【发布时间】:2012-08-25 22:21:27
【问题描述】:

我想在编译时声明我的 C 程序中的所有变量,例如:

char cache[CACHE_SIZE];
char udp_ring[MAX_UDP_PACKET_SIZE*MAX_REQUESTS];
int  num_packets;
char error_codes[NUM_ERRORS][MAX_ERROR_STRING]= {
    {"Unknown user\n"},
    {"Wrong password\n"},
    ....
};

问题是,当 C 程序中的变量进入 BSS 或 DATA 段时,它们的大小是否有任何限制? 例如,如果我声明 8GB RAM 的 CACHE_SIZE,它会起作用吗? 32位或64位有什么区别吗?我打算在 Linux 上运行程序,我的 RLIMIT_DATA 配置将没有限制。

【问题讨论】:

  • “我想在编译时声明我的 C 程序中的所有变量”——那么有办法在运行时声明它们吗?
  • 是的,但是我不想和glibc链接,所以我需要避免malloc()
  • sigh - 声明变量不是你想的那样。您不能在运行时声明变量。去拿一本 C 书。
  • C 中的变量在源代码中声明,在其编译对象 (.obj) 代码中没有任何直接表示。
  • @H2CO3 我相信OP希望静态分配程序中的所有变量。

标签: c linux


【解决方案1】:

您将能够管理内核允许进程处理的尽可能多的虚拟内存:这取决于架构。

例如,在 x86 架构上(没有 x86-64 长模式),Linux 默认将进程看到的虚拟内存拆分为 3GB 用于进程,1GB 用于内核(即使启用了 PAE):您的进程将无法处理超过 3GB 的虚拟内存(包括文本部分、数据、bss、堆、堆栈、共享对象等)

如果您静态分配所有缓冲区并且内核无法将其放入进程虚拟地址空间,它将在启动时被终止:使用 8GB 缓冲区将主要导致在 32 位架构上出现这种行为。

如果您不想依赖 glibc 的内存管理功能(malloc,...),您可以滚动自己的内存管理库并强制您的进程使用 LD_PRELOAD 技巧,这样您可以定义一个符合您自己要求的malloc/calloc/realloc/free(使用sbrk())实现。

【讨论】:

  • 好的,据我了解,在 64 位模式下静态分配的变量没有限制,是初始化(BSS)还是不初始化(DATA),对吗?
  • 对 64 位架构有 个虚拟限制,即 2^64 字节(16 艾字节)的虚拟地址空间减去为寻址内核而保留的一些空间。但是,x86-64(AMD 和 Intel)的当前实现仅限于 48 位地址位(约 256 TB 的虚拟地址空间),但我很确定在达到此限制之前您会用完物理 RAM。 IIRC Linux 在 x86-64 上允许每个进程 128TB 的虚拟地址空间。
【解决方案2】:

如果你不想与glibc 链接,你应该找到一些奇怪的方法来实现syscalls(在syscalls(2) 手册页中列出)。任何应用程序都必须执行一些系统调用(例如open(2)read(2)write(2) ...)。 Glibc 还用于为系统调用提供 C 接口。 assembly howto 解释了如何在没有 libc 的情况下调用系统调用,直接使用一些汇编代码(例如通过 C asm 指令)。另请参阅过时的 _syscall(2) 手册页。还要寻找VDSO

您可以使用mmap(2)munmap(2) 系统调用来更改您的地址空间。这是分配和释放内存的基本操作。 Glibc 使用它们来实现mallocfree

将所有变量声明为全局变量或静态变量,无论是初始化(.data 段)还是清除(.bss 段)都有一个明显的缺点:您不能动态使用内存资源。并且拥有大量初始化数据会产生巨大的成本:您的 ELF 可执行文件将非常庞大。

但是您确实应该解释为什么要避免使用 Glibc。用 C 编码时很难避免它。您可以使用更轻的替代方案,例如 dietlibc

【讨论】:

  • 谢谢,非常有用的信息。我想避免使用 glibc,因为我将以二进制形式分发程序,并且我不想遇到与不同 linux 发行版不兼容的问题。实际上我将使用动态分配,但它只适用于我自己的堆管理例程的缓存,我只是想知道其他变量的限制。
  • 您可能会考虑静态链接 Glibc,但这通常是个坏主意。你应该解释你正在编写什么样的程序。您是否考虑过使其成为免费软件(例如 GPL 许可)?甚至静态链接你的 Glibc 也不会避免所有的不兼容性;一些 Glibc 稍微依赖于内核版本...
猜你喜欢
  • 2014-02-03
  • 2016-08-06
  • 2015-05-31
  • 2020-05-25
  • 1970-01-01
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 2012-10-14
相关资源
最近更新 更多