我想在编译时声明我的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配置没有限制。
答案 0 :(得分:4)
您将能够管理内核允许进程处理的虚拟内存:它将取决于体系结构。
例如,在x86架构上(没有x86-64长模式),Linux默认情况下将进程看到的虚拟内存分为3GB进程和内核1GB(即使PAE已启用):您的进程将无法处理超过3GB的虚拟内存(包括文本部分,数据,bss,堆,堆栈,共享对象等)。
如果静态分配所有缓冲区并且内核无法将其放入进程虚拟地址空间,则它将在启动时被终止:使用8GB缓冲区将主要导致32位体系结构中的此行为。< / p>
如果你不想依赖glibc的内存管理功能(malloc
,...),你可以推出自己的内存管理库并强制你的进程使用LD_PRELOAD
诀窍,这样你就可以定义符合你自己要求的malloc/calloc/realloc/free
(使用sbrk()
)实现。
答案 1 :(得分:2)
如果您不想与glibc
关联,您应该找到一些奇怪的方法来syscalls(在syscalls(2)手册页中列出)。任何应用程序都必须执行一些系统调用(例如open(2),read(2),write(2) ...)。 Glibc还用于为系统调用提供C接口。 assembly howto解释了如何在没有libc的情况下调用syscalls,直接使用一些汇编代码(例如通过C asm
指令)。另请参见过时的_syscall(2)手册页。另请参阅VDSO。
您可以使用mmap(2)和munmap(2)
系统调用来更改地址空间。这是分配和释放内存的基本操作。 Glibc使用它们来实现malloc
和free
。
将所有变量声明为全局或静态,无论是初始化(.data
段)还是已清除(.bss
段)都有一个明显的缺点:您无法使用动态内存资源。并且拥有大量初始化数据会产生巨大的成本:您的ELF可执行文件会非常庞大。
但你真的应该解释为什么你要避免Glibc。在用C编码时很难避免它。你可以使用更轻的替代品,如dietlibc。