Contamos con tu apoyo para compartir nuestros tutoriales referente a las ciencias de la computación.
Solución:
Él .bss
Se garantiza que la sección sea todo ceros cuando el programa se cargue en la memoria. Por lo tanto, cualquier dato global que no esté inicializado o inicializado a cero se coloca en el .bss
sección. Por ejemplo:
static int g_myGlobal = 0; // <--- in .bss section
Lo bueno de esto es que la .bss
los datos de la sección no tienen que incluirse en el archivo ELF en el disco (es decir, no hay una región completa de ceros en el archivo para el .bss
sección). En su lugar, el cargador sabe a partir de los encabezados de sección cuánto asignar para el .bss
y simplemente póngalo a cero antes de entregar el control a su programa.
Observe la readelf
producción:
[ 3] .data PROGBITS 00000000 000110 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 000110 000000 00 WA 0 0 4
.data
está marcado como PROGBITS
. Eso significa que hay "bits" de datos de programa en el archivo ELF que el cargador necesita leer en la memoria por usted. .bss
por otro lado está marcado NOBITS
lo que significa que no hay nada en el archivo que deba leerse en la memoria como parte de la carga.
Ejemplo:
// bss.c
static int g_myGlobal = 0;
int main(int argc, char** argv)
return 0;
compilarlo con $ gcc -m32 -Xlinker -Map=bss.map -o bss bss.c
Mire los encabezados de sección con $ readelf -S bss
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
:
[13] .text PROGBITS 080482d0 0002d0 000174 00 AX 0 0 16
:
[24] .data PROGBITS 0804964c 00064c 000004 00 WA 0 0 4
[25] .bss NOBITS 08049650 000650 000008 00 WA 0 0 4
:
Ahora buscamos nuestra variable en la tabla de símbolos: $ readelf -s bss | grep g_myGlobal
37: 08049654 4 OBJECT LOCAL DEFAULT 25 g_myGlobal
Tenga en cuenta que g_myGlobal
se muestra como parte de la sección 25. Si miramos hacia atrás en los encabezados de la sección, vemos que 25 es .bss
.
Para responder a su verdadera pregunta:
Aquí, en el programa anterior, no tengo ningún dato no inicializado, pero el BSS ha ocupado 8 bytes. ¿Por qué ocupa 8 bytes?
Siguiendo con mi ejemplo, buscamos cualquier símbolo en la sección 25:
$ readelf -s bss | grep 25
9: 0804825c 0 SECTION LOCAL DEFAULT 9
25: 08049650 0 SECTION LOCAL DEFAULT 25
32: 08049650 1 OBJECT LOCAL DEFAULT 25 completed.5745
37: 08049654 4 OBJECT LOCAL DEFAULT 25 g_myGlobal
La tercera columna es el tamaño. Vemos nuestro esperado 4 bytes g_myGlobal
y este 1 byte completed.5745
. Esta es probablemente una función-static variable de algún lugar en la inicialización del tiempo de ejecución de C; recuerde, muchas "cosas" suceden antes main()
se llama alguna vez.
4+1=5 bytes. Sin embargo, si miramos hacia atrás en el .bss
encabezado de la sección, vemos la última columna Al
es 4. Esa es la alineación de la sección, lo que significa que esta sección, cuando se carga, siempre será un múltiplo de 4 bytes. El siguiente múltiplo de 5 es 8, y es por eso que el .bss
la sección es de 8 bytes.
Además Podemos mirar el archivo de mapa generado por el enlazador para ver qué archivos de objetos se colocaron en el resultado final.
.bss 0x0000000008049650 0x8
*(.dynbss)
.dynbss 0x0000000000000000 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
*(.bss .bss.* .gnu.linkonce.b.*)
.bss 0x0000000008049650 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
.bss 0x0000000008049650 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crti.o
.bss 0x0000000008049650 0x1 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtbegin.o
.bss 0x0000000008049654 0x4 /tmp/ccKF6q1g.o
.bss 0x0000000008049658 0x0 /usr/lib/libc_nonshared.a(elf-init.oS)
.bss 0x0000000008049658 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtend.o
.bss 0x0000000008049658 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crtn.o
Una vez más, la tercera columna es el tamaño.
Vemos 4 bytes de .bss
vino de /tmp/ccKF6q1g.o
. En este ejemplo trivial, sabemos que es el archivo de objeto temporal de la compilación de nuestro archivo bss.c. El otro 1 byte vino de crtbegin.o
que es parte del tiempo de ejecución de C.
Finalmente, dado que sabemos que esta variable bss misteriosa de 1 byte es de crtbegin.o
y se llama completed.xxxx
su verdadero nombre es completed
y probablemente sea un static dentro de alguna función. Mirando a crtstuff.c
encontramos al culpable: un static _Bool completed
dentro de __do_global_dtors_aux()
.
Por definición, el segmento bss ocupa algún lugar en la memoria (cuando se inicia el programa) pero no necesita espacio en disco. Necesita definir alguna variable para llenarla, así que intente
int bigvar_in_bss[16300];
int var_in_data[5] = 1,2,3,4,5;
Es posible que su programa simple no tenga ningún dato en .bss
y bibliotecas compartidas (como libc.so
) pueden tener "su propia .bss
"
Los desplazamientos de archivos y las direcciones de memoria no se relacionan fácilmente.
Lea más sobre la especificación ELF, también use /proc/
(p.ej cat /proc/self/maps
mostraría el espacio de direcciones del cat
proceso que ejecuta ese comando). Lea también proc(5)
Sección de Reseñas y Valoraciones
Recuerda algo, que tienes la capacidad de reseñar tu experiencia si te ayudó.