bss和数据的最大大小

Nul*_*lik 6 c linux

我想在编译时声明我的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"},
    ....
};
Run Code Online (Sandbox Code Playgroud)

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

str*_*rnk 5

您将能够管理与内核允许进程处理一样多的虚拟内存:这取决于体系结构。

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

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

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

  • 64 位架构有一个虚拟限制,即 2^64 字节(16 艾字节)的虚拟地址空间减去保留用于寻址内核的一些空间。然而,x86-64(AMD 和 Intel)的当前实现仅限于 48 位地址位(约 256 TB 的虚拟地址空间),但我很确定在达到此限制之前您将耗尽物理 RAM。IIRC Linux 在 x86-64 上允许每个进程使用 128TB 的虚拟地址空间。 (3认同)

Bas*_*tch 5

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

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

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

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