una - llamadas al sistema(< system calls>)
¿Cómo hacen las aplicaciones de 32 bits las llamadas al sistema en Linux de 64 bits? (1)
Desde el lado del espacio de usuario, la mecánica es idéntica a hacer un syscall en un kernel nativo de 32 bits: todo el código de modo de usuario, incluido el glibc de 32 bits, funciona de la misma manera.
Desde el lado del kernel, los antiguos puntos de entrada IA32 del espacio de usuario (por ejemplo, int 0x80
) están configurados para llamar a la rutina del ensamblador ia32_syscall
. (La transición al espacio del kernel implica que el procesador cargue el selector de segmento de código del kernel, lo que provoca una transición al modo "largo" de 64 bits).
La rutina ia32_syscall
luego baraja algunos de los argumentos para que coincidan con la convención de llamada syscall x86_64:
movl %edi,%r8d
.if /noebp
.else
movl %ebp,%r9d
.endif
xchg %ecx,%esi
movl %ebx,%edi
movl %edx,%edx /* zero extension */
Luego utiliza el número de syscall IA32 para realizar una llamada a la función a través de una tabla, ia32_sys_call_table
. Básicamente, esto hace coincidir los números de syscall de IA32 con las implementaciones de syscall nativas (los números de syscall difieren enormemente entre IA32 y x86_64). La primera parte de esta tabla se ve así:
ia32_sys_call_table:
.quad sys_restart_syscall
.quad sys_exit
.quad stub32_fork
.quad sys_read
.quad sys_write
Para la mayoría de los syscalls, la implementación x86_64 ahora se puede llamar directamente, como exit()
. Para otros, como fork()
, se proporciona una envoltura que implementa correctamente la semántica IA32 esperada (en particular, si se requiere la extensión de signo de los argumentos de 32 a 64 bits).
Como puede ver, la sobrecarga en el código del kernel es mínima: algunas modificaciones triviales para registrar valores, y para algunas funciones, una llamada a función adicional. No estoy seguro de que cargar un selector de segmento de código que cause una transición del modo de 32 bits al modo de 64 bits sea más lento para que el procesador se ejecute que uno que no lo haga; consulte los manuales de arquitectura del procesador para eso.
Algunas (¿muchas? Todas?) Distribuciones de Linux de 64 bits 1 permiten ejecutar aplicaciones de 32 bits mediante el envío de colecciones paralelas de bibliotecas de 32 bits y de 64 bits (incluida libc). Por lo tanto, una aplicación de 32 bits puede vincularse con libs de 32 bits y ser ejecutada por un kernel de 64 bits.
Me gustaría conocer la mecánica de cómo las aplicaciones de 32 bits realizan llamadas al sistema en un kernel de 64 bits. Sospecho que la respuesta está en algún lugar de libc y / o la fuente del kernel, pero me llevaría mucho tiempo sumergirme en la fuente ya que no sé dónde buscar.
Y una pregunta más importante, ¿hay alguna sobrecarga de rendimiento? 2 Lógicamente, una llamada de un sistema de aplicación de 32 bits deberá traducirse a un entorno interno de kernel de 64 bits. ¿Cómo y dónde se logra esto?
1 "32 bits" = IA-32, y "64 bits" = AMD64
2 En tu respuesta, haz una suposición de que importa :)