stringtranslate.com

error de autobús

En informática , un error de bus es una falla provocada por el hardware, que notifica a un sistema operativo (SO) que un proceso está intentando acceder a una memoria que la CPU no puede abordar 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 en los permisos.

En plataformas compatibles con POSIX , los errores de bus generalmente provocan que la señal SIGBUS se envíe al proceso que causó el error. SIGBUS también puede ser causado por cualquier falla general del dispositivo que detecte la computadora, aunque un error de bus rara vez significa que el hardware de la computadora esté físicamente roto; normalmente es causado por un error en el software . [ cita necesaria ] Los errores de bus también pueden surgir para otros errores de paginación; vea abajo.

Causas

Hay al menos tres causas principales de errores de bus:

dirección inexistente

El software 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 todo el resto del hardware conectado a la CPU que responda con los resultados, si responden por esta dirección específica. Si ningún otro hardware responde, la CPU genera una excepción , indicando que todo el sistema informático no reconoce la dirección física solicitada. Tenga en cuenta que esto sólo cubre direcciones de memoria física . Intentar acceder a una dirección de memoria virtual no definida generalmente se considera una falla 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 bytes , 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 (siendo la plataforma x86 una excepción notable). ).

Por ejemplo, si los accesos de varios bytes deben estar alineados con 16 bits, las direcciones (dadas en bytes) en 0, 2, 4, 6, etc. se considerarán alineadas y, por lo tanto, accesibles, mientras que las direcciones 1, 3, 5 y y así sucesivamente se considerarían no alineados. De manera similar, si los accesos de varios bytes 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 según la arquitectura que se utilice. Por ejemplo, para hardware basado en el mainframe IBM System/360 , incluido 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 incluso byte. Los intentos de bifurcarse a una dirección impar dan como resultado una excepción de especificación. [1] Sin embargo, los datos se pueden recuperar de cualquier dirección en la memoria y pueden tener un byte o más, según 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 cambian 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 a 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 acceso a memoria no alineado.

Errores de paginación

FreeBSD , Linux y Solaris pueden indicar un error de bus cuando las páginas de la memoria virtual no se pueden paginar , por ejemplo, porque han desaparecido (por ejemplo, al acceder a un archivo asignado en memoria o al ejecutar una imagen binaria que se ha truncado mientras el programa se estaba ejecutando), [2 ] [ ¿ fuente poco confiable? ] o porque un archivo asignado 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 administració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 usaban eso para intercambiar, pero en Linux esto genera SIGBUS.

Ejemplo

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

#incluir <stdlib.h> int principal ( int argc , char ** argv ) { int * iptr ; char * cptr ; #if definido(__GNUC__) # si definido(__i386__) /* Habilitar verificación de alineación en x86 */ __asm__ ( "pushf \n orl $0x40000,(%esp) \n popf" ); # elif definido(__x86_64__) /* Habilitar verificació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, desalineándolo */ iptr = ( int * ) ++ cptr ;             /* Elimina la referencia como puntero int, provocando un acceso no alineado */ * iptr = 42 ;    /*  Los siguientes accesos también generarán un error de sigbus.  corto *sptr;  ent i; sptr = (corto *)&i;  // Para todos los incrementos de valores impares, el resultado será sigbus.  sptr = (corto *)(((char *)sptr) + 1);  *espr = 100;  */  devolver 0 ; } 

La compilación y ejecución del ejemplo en un sistema operativo compatible con POSIX en x86 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 principal () (gdb) x/i $pc 0x80483ba <principal+54>: mov DWORD PTR [eax],0x2a (gdb) p/x $eax $ 1 = 0x804a009 (gdb) p/t $eax & ( tamaño de (int) - 1) $ 2 = 1          

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

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

Referencias

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