stringtranslate.com

Error de bus

En informática , un error de bus es un fallo provocado por el hardware, que notifica a un sistema operativo (OS) que un proceso está intentando acceder a una memoria a la que la CPU no puede acceder físicamente: una dirección no válida para el bus de direcciones , de ahí el nombre. En el uso moderno en la mayoría de las arquitecturas, estos son mucho más raros que los fallos de segmentación , que ocurren principalmente debido a violaciones de acceso a la memoria: problemas en la dirección lógica o permisos.

En las plataformas compatibles con POSIX , los errores de bus suelen provocar el envío de la señal SIGBUS al proceso que causó el error. SIGBUS también puede ser causado por cualquier fallo general del dispositivo que detecte la computadora, aunque un error de bus rara vez significa que el hardware de la computadora esté dañado físicamente; normalmente es causado por un error en el software . [ cita requerida ] Los errores de bus también pueden surgir por otros errores de paginación determinados; consulte a continuación.

Causas

Existen al menos tres causas principales de errores de bus:

Dirección inexistente

El software le indica a la CPU que lea o escriba una dirección de memoria física específica . En consecuencia, la CPU establece esta dirección física en su bus de direcciones y solicita a todos los demás dispositivos conectados a la CPU que respondan con los resultados, si responden para esta dirección específica. Si ningún otro dispositivo responde, la CPU genera una excepción , indicando que la dirección física solicitada no es reconocida por todo el sistema informático. Tenga en cuenta que esto solo cubre las direcciones de memoria física . Intentar acceder a una dirección de memoria virtual no definida generalmente se considera un error de segmentación en lugar de un error de bus, aunque si la MMU está separada, el procesador no puede notar la diferencia.

Acceso no alineado

La mayoría de las CPU son direccionables por byte , donde cada dirección de memoria única se refiere a un byte de 8 bits . La mayoría de las CPU pueden acceder a bytes individuales desde cada dirección de memoria, pero generalmente no pueden acceder a unidades más grandes (16 bits, 32 bits, 64 bits, etc.) sin que estas unidades estén " alineadas " con un límite específico (la plataforma x86 es una notable excepción).

Por ejemplo, si los accesos multibyte deben estar alineados con 16 bits, las direcciones (indicadas en bytes) en 0, 2, 4, 6, etc. se considerarían alineadas y, por lo tanto, accesibles, mientras que las direcciones 1, 3, 5, etc. se considerarían no alineadas. De manera similar, si los accesos multibyte deben estar alineados con 32 bits, las direcciones 0, 4, 8, 12, etc. se considerarían alineadas y, por lo tanto, accesibles, y todas las direcciones intermedias se considerarían no alineadas. Intentar acceder a una unidad mayor que un byte en una dirección no alineada puede provocar un error de bus.

Algunos sistemas pueden tener un híbrido de estos, dependiendo de la arquitectura que se utilice. Por ejemplo, para el hardware basado en el mainframe IBM System/360 , incluyendo IBM System z , Fujitsu B8000, RCA Spectra y UNIVAC Series 90 , las instrucciones deben estar en un límite de 16 bits, es decir, las direcciones de ejecución deben comenzar en un byte par. Los intentos de ramificar a una dirección impar resultan en una excepción de especificación. [1] Los datos, sin embargo, pueden ser recuperados desde cualquier dirección en la memoria, y pueden ser de un byte o más dependiendo de la instrucción.

Las CPU generalmente acceden a los datos en todo el ancho de su bus de datos en todo momento. Para direccionar bytes, acceden a la memoria en todo el ancho de su bus de datos, luego enmascaran y desplazan para direccionar el byte individual. Los sistemas toleran este algoritmo ineficiente, ya que es una característica esencial para la mayoría del software, especialmente el procesamiento de cadenas . A diferencia de los bytes, las unidades más grandes pueden abarcar dos direcciones alineadas y, por lo tanto, requerirían más de una búsqueda en el bus de datos. Es posible que las CPU admitan esto, pero esta funcionalidad rara vez se requiere directamente en el nivel de código de máquina , por lo que los diseñadores de CPU normalmente evitan implementarla y, en su lugar, emiten errores de bus para el acceso a la memoria no alineada.

Errores de paginación

FreeBSD , Linux y Solaris pueden señalar un error de bus cuando no se pueden paginar páginas de memoria virtual , por ejemplo, porque ha desaparecido (por ejemplo, al acceder a un archivo mapeado en memoria o al ejecutar una imagen binaria que se ha truncado mientras se ejecutaba el programa), [2] [¿ fuente no confiable? ] o porque un archivo mapeado en memoria recién creado no se puede asignar físicamente, porque el disco está lleno.

Segmento no presente (x86)

En x86 existe un mecanismo de gestión de memoria más antiguo conocido como segmentación . Si la aplicación carga un registro de segmento con el selector de un segmento no presente (lo que en sistemas operativos compatibles con POSIX solo se puede hacer con lenguaje ensamblador ), se genera la excepción. Algunos sistemas operativos lo usaban para el intercambio, pero en Linux esto genera SIGBUS.

Ejemplo

Este es un ejemplo de acceso a memoria no alineada, escrito en el lenguaje de programación C con sintaxis de ensamblaje AT&T .

#incluir <stdlib.h> int main ( int argc , char ** argv ) { int * iptr ; char * cptr ; #if definido(__GNUC__) # if definido(__i386__) /* Habilitar comprobación de alineación en x86 */ __asm__ ( "pushf \n orl $0x40000,(%esp) \n popf" ); # elif definido(__x86_64__) /* Habilitar comprobación de alineación en x86_64 */ __asm__ ( "pushf \n orl $0x40000,(%rsp) \n popf" ); # endif #endif               /* malloc() siempre proporciona memoria alineada para todos los tipos fundamentales */ cptr = malloc ( sizeof ( int ) + 1 ); /* Incrementa el puntero en uno, haciéndolo desalineado */ iptr = ( int * ) ++ cptr ;             /* Desreferenciarlo como un puntero int, causando un acceso no alineado */ * iptr = 42 ;    /*  Los siguientes accesos también provocarán un error sigbus.  short *sptr;  int i; sptr = (short *)&i;  // Para todos los incrementos de valores impares, el resultado será sigbus.  sptr = (short *)(((char *)sptr) + 1);  *sptr = 100;  */  devuelve 0 ; } 

Al compilar y ejecutar el ejemplo en un sistema operativo compatible con POSIX en x86 se demuestra el error:

$ gcc  -ansi  sigbus.c  -o  sigbus $ ./sigbus Error de bus $ gdb ./sigbus (gdb) r El programa recibió la señal SIGBUS, Error de bus. 0x080483ba en main () (gdb) x/i $pc 0x80483ba <main+54>: mov DWORD PTR [eax],0x2a (gdb) p/x $eax $ 1 = 0x804a009 (gdb) p/t $eax & (sizeof(int) - 1) $ 2 = 1          

El depurador GDB muestra que el valor inmediato 0x2a se almacena en la ubicación almacenada en el registro EAX , mediante el lenguaje ensamblador X86 . Este es un ejemplo de direccionamiento indirecto de registros .

La impresión de los bits de orden bajo de la dirección muestra que no está alineada con un límite de palabra ("dword" usando la terminología x86).

Referencias

  1. ^ z/Architecture Principles of Operation , SA22-7832-04, página 6-6, quinta edición (septiembre de 2005) IBM Corporation, Poukeepsie, NY, recuperable en http://publibfp.dhe.ibm.com/epubs/pdf/a2278324.pdf Archivado el 22 de mayo de 2022 en Wayback Machine. (Consultado el 31 de diciembre de 2015)
  2. ^ "¿Qué es SIGBUS - Error de hardware específico del objeto?".