8

我想在编译时声明我的 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 配置没有任何限制。

4

2 回答 2

6

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

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

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

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

于 2012-08-25T23:00:08.733 回答
4

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

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

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

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

于 2012-08-26T07:04:38.427 回答