2012-08-25 19 views
5

Quiero declarar todas las variables en mi programa de C en tiempo de compilación, como por ejemplo:tamaño máximo de BSS y datos

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"}, 
    .... 
}; 

La pregunta es, ¿hay límites en el tamaño de las variables en un programa C cuando van en BSS o segmento de DATOS? Por ejemplo, si declaro CACHE_SIZE de 8 GB de RAM, ¿funcionará? ¿Hay alguna diferencia para 32 bits o 64 bits? Planeo ejecutar el programa en Linux y no habrá restricciones en mi configuración de RLIMIT_DATA.

+0

"Quiero declarar todas las variables en mi programa C en el momento de la compilación", por lo que hay una manera de declararlas en tiempo de ejecución? –

+0

sí, pero no quiero vincular con glibc, entonces debo evitar malloc() – Nulik

+2

** suspiro ** - declarar una variable no es lo que piensas que es. No puede declarar una variable en tiempo de ejecución. Ve a buscar un libro C. –

Respuesta

3

Podrá administrar la mayor cantidad de memoria virtual que su núcleo permita a los procesos manejar: dependerá de la arquitectura.

Por ejemplo, en una arquitectura x86 (sin modo largo x86-64), Linux divide por defecto la memoria virtual vista por un proceso en 3GB para el proceso y 1GB para el kernel (incluso si PAE está habilitado): su proceso no podrá manejar más de 3GB de memoria virtual (incluye secciones de texto, datos, bss, montón, pila, objetos compartidos, etc.)

Si asigna todo su buffer estáticamente y el kernel no puede encajarlo en el espacio de direcciones virtuales del proceso, se eliminará al iniciarse: el uso de un búfer de 8GB resultará principalmente en este comportamiento en una arquitectura de 32 bits.

Si no quiere confiar en la función de gestión de memoria de glibc (malloc, ...), puede rodar su propia biblioteca de administración de memoria y forzar su proceso para usarla con un truco LD_PRELOAD, de esa manera podría definir una implementación de malloc/calloc/realloc/free (usando sbrk()) que coincida con sus propios requisitos.

+0

bien, como entendí, no hay límite para las variables asignadas estáticamente en el modo de 64 bits ¿se inicializaría (BSS) o no se inicializaría (DATA), correcto? – Nulik

+1

There * is * es un límite virtual en las arquitecturas de 64 bits, que sería de 2^64 bytes (16 exabytes) de espacio de direcciones virtuales menos algún espacio reservado para direccionar el kernel. Sin embargo, las implementaciones actuales de x86-64 (AMD e Intel) están limitadas a 48 bits de bits de dirección (~ 256 TB de espacio de direcciones virtuales), pero estoy bastante seguro de que se agotará la memoria RAM física antes de alcanzar este límite. IIRC Linux permite 128 TB de espacio de direcciones virtuales por proceso en x86-64. – strnk

2

Si no desea vincular con glibc, debe encontrar algunas formas extrañas de poder hacer syscalls (enumeradas en la página de manual de syscalls(2)). Cualquier aplicación tiene que hacer algunas llamadas de sistema (por ejemplo, open(2), read(2), write(2) ...). Glibc también se usa para proporcionar una interfaz C para llamadas de sistema. El assembly howto explica cómo llamar a syscalls sin libc, directamente utilizando algún código de ensamblaje (por ejemplo, a través de las instrucciones C asm). Consulte también la página del manual _syscall(2) obsoleta. Busque también VDSO.

Puede cambiar su espacio de direcciones utilizando mmap(2) y munmap(2) syscalls. Estas son las operaciones elementales para asignar y liberar memoria. Glibc los usa para implementar malloc y free.

Declarar todas las variables como globales o estáticas, ya sea inicializadas (segmento .data) o borradas (segmento .bss) tiene una desventaja significativa: no se pueden usar dinámicamente recursos de memoria. Y tener una gran cantidad de datos inicializados tiene un costo significativo: su ejecutable ELF sería enorme.

Pero realmente debería explicar por qué quiere evitar Glibc. Es difícil evitarlo al codificar en C. Puede usar alternativas más ligeras como dietlibc.

+0

gracias, información muy útil. Quiero evitar glibc porque distribuiré el programa en forma binaria, y no quiero tener problemas de incompatibilidad con diferentes distribuciones de Linux. En realidad, utilizaré la asignación dinámica, pero será solo para la caché con mis propias rutinas de administración de heap, solo quería saber los límites para las otras variables. – Nulik

+0

Quizás considere la posibilidad de vincular estáticamente Glibc, pero esta suele ser una mala idea. Debe explicar qué tipo de programa está codificando. ¿Consideró que es un software gratuito (por ejemplo, licencia GPL)? E incluso vincular estáticamente tu Glibc no evitará todas las incompatibilidades; algunos de Glibc dependen ligeramente de la versión del kernel ... –