问题
I want to declare all the variables in my C program at compile time, like for example:
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"},
....
};
The question is, are there any limits on the size of the variables in a C program when they go in BSS or DATA segment? For example if I declare CACHE_SIZE of 8GB of RAM, will it work? Is there any difference for 32 bits or 64 bits? I plan to run the program on Linux and there will be no restriction in my RLIMIT_DATA configuration.
回答1:
You will be able to manage as much virtual memory as your kernel allows processes to handle : it will depend on the architecture.
For example, on a x86 architecture (without x86-64 long mode), Linux splits by default the virtual memory seen by a process in 3GB for the process and 1GB for the kernel (even if PAE is enabled) : your process won't be able to handle more than 3GB of virtual memory (include text sections, data, bss, heap, stack, shared objects, etc.)
If you allocate all your buffer statically and the kernel cannot fit it in the process virtual address space, it will be killed at start-up : using a 8GB buffer will mostly result in this behavior on a 32-bit architecture.
If you don't want to rely on glibc's memory management function (malloc
, ...), you could roll your own memory management library and force your process to use it with a LD_PRELOAD
trick, that way you could define a malloc/calloc/realloc/free
(using sbrk()
) implementation matching your own requirements.
回答2:
If you don't want to link with glibc
, you should find some weird ways to be able to do syscalls (listed in syscalls(2) man page). Any application has to do some syscalls (e.g. open(2), read(2), write(2) ...). Glibc is also used to provide a C interface to syscalls. The assembly howto explains how to call syscalls without libc, directly using some assembly code (e.g. thru C asm
instructions). See also the obsolete _syscall(2) man page. Look also for VDSO.
You can change your address space using the mmap(2) and munmap(2)
syscalls. This is the elementary operations for allocating and releasing memory. Glibc uses them to implement malloc
and free
.
Declaring all variables as global or static, be it initialized (.data
segment) or cleared (.bss
segment) has a significant disadvantage: you cannot use dynamically memory resources. And having a lot of initialized data have a significant cost: your ELF executable would be huge.
But you really should explain why you want to avoid Glibc. It is hard to avoid it when coding in C. You could use lighter alternatives like dietlibc.
来源:https://stackoverflow.com/questions/12126103/maximum-size-of-bss-and-data