¿Dónde encuentra la tabla syscall para Linux?


13

Veo a muchas personas haciendo referencia en línea

arch/x86/entry/syscalls/syscall_64.tbl

para la tabla syscall, eso funciona bien. Pero muchos otros hacen referencia

/include/uapi/asm-generic/unistd.h

que se encuentra comúnmente en el paquete de encabezados. ¿Cómo es que los syscall_64.tblespectáculos,

0 common  read      sys_read

La respuesta correcta, y unistd.hmuestra,

#define __NR_io_setup 0
__SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)

Y luego se muestra __NR_readcomo

#define __NR_read 63
__SYSCALL(__NR_read, sys_read)

¿Por qué es eso 63 y no 1? ¿Cómo tengo sentido fuera de /include/uapi/asm-generic/unistd.h? Todavía /usr/include/asm/hay

/usr/include/asm/unistd_x32.h
#define __NR_read (__X32_SYSCALL_BIT + 0)
#define __NR_write (__X32_SYSCALL_BIT + 1)
#define __NR_open (__X32_SYSCALL_BIT + 2)
#define __NR_close (__X32_SYSCALL_BIT + 3)
#define __NR_stat (__X32_SYSCALL_BIT + 4)

/usr/include/asm/unistd_64.h
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4

/usr/include/asm/unistd_32.h
#define __NR_restart_syscall 0
#define __NR_exit 1           
#define __NR_fork 2           
#define __NR_read 3           
#define __NR_write 4          

¿Podría alguien decirme la diferencia entre estos unistdarchivos? Explicar cómo unistd.hfunciona ¿Y cuál es el mejor método para encontrar la tabla syscall?

Respuestas:


12

Cuando estoy investigando este tipo de cosas, me resulta útil preguntarle directamente al compilador (vea Imprimir macros predefinidas C / GCC estándar en la terminal para más detalles):

printf SYS_read | gcc -include sys/syscall.h -E -

Esto demuestra que las cabeceras involucradas (en Debian) son /usr/include/x86_64-linux-gnu/sys/syscall.h, /usr/include/x86_64-linux-gnu/asm/unistd.h, /usr/include/x86_64-linux-gnu/asm/unistd_64.h, y /usr/include/x86_64-linux-gnu/bits/syscall.h, e imprime el número de llamadas al sistema para read, que es 0 en x86-64.

Puede encontrar los números de llamada del sistema para otras arquitecturas si tiene instalados los encabezados del sistema apropiados (en un entorno de compilación cruzada). Para x86 de 32 bits es bastante fácil:

printf SYS_read | gcc -include sys/syscall.h -m32 -E -

que implica /usr/include/asm/unistd_32.hentre otros archivos de encabezado e imprime el número 3.

Entonces, desde la perspectiva del espacio de usuario, las llamadas al sistema x86 de 32 bits se definen en asm/unistd_32.hlas llamadas al sistema x86 de 64 bits asm/unistd_64.h. asm/unistd_x32.hse usa para el x32 ABI .

uapi/asm-generic/unistd.h enumera las llamadas predeterminadas del sistema, que se utilizan en arquitecturas que no tienen una tabla de llamadas del sistema específica de la arquitectura.

En el núcleo, las referencias son ligeramente diferentes y son específicas de la arquitectura (de nuevo, para arquitecturas que no usan la tabla genérica de llamadas al sistema). Aquí es donde arch/x86/entry/syscalls/syscall_64.tblentran los archivos como (y finalmente terminan produciendo los archivos de encabezado que se utilizan en el espacio del usuario, unistd_64.hetc.). Encontrará muchos más detalles sobre las llamadas al sistema en el par de artículos de LWN sobre el tema, Anatomía de una llamada al sistema parte 1 y Anatomía de una llamada al sistema parte 2 .


¿Es estable la tabla syscall entre la versión del kernel de Linux y las futuras?
Biswapriyo

@Biswapriyo es, eso es parte de la estabilidad ABI que los desarrolladores del kernel siempre intentan preservar. Se pueden agregar nuevas llamadas al sistema, pero las antiguas no cambian, excepto en un número muy pequeño de casos extremos (como la tuxllamada al sistema ).
Stephen Kitt


7

63 está readadentro arm64, 0 está readadentrox86_64

Los números de syscall son diferentes para cada arquitectura.

Los números de arm64, por ejemplo, se definen en: include/uapi/asm-generic/unistd.hque muestra que 63, vea también: /reverseengineering/16917/arm64-syscalls-table/18834#18834

Como se explicó en esa respuesta, creo que include / uapi / asm-generic / unistd.h es un nuevo intento de unificar los números de syscall en todos los arcos.

Pero como los números de syscall no pueden cambiar para no romper la API de syscall, los arcos anteriores a ese esfuerzo de unificación han mantenido los números antiguos.

Esta pregunta solicita una forma automatizada de obtener la lista completa de syscall, incluidos los parámetros: /programming/6604007/how-can-i-get-a-list-of-linux-system-calls-and- número-de-args-se-toman-automati

strace código fuente

Confío en esa herramienta y mantienen sus datos ordenados linux/, por ejemplo:

Tenga en cuenta que el aarch64 #includees el agnóstico de arco al 64/syscallent.hque me referí anteriormente.

Esas tablas contienen el número de argumentos, pero no los tipos de argumentos reales, me pregunto dónde los stracecodifica.


3

Esta respuesta no tocará la asm-genericversión de unistd.h, porque nada la incluye. 1

Como se señala en syscalls(2):

En términos generales, el código que pertenece a la llamada al sistema con el número __NR_xxx definido en /usr/include/asm/unistd.hse puede encontrar en la fuente del kernel de Linux en la rutina sys_xxx().

Es decir, se encontrarán los números correctos de syscall /usr/include/asm/unistd.h. Ahora, en un sistema x86 típico, esto simplemente incluirá uno de los asm/unistd_*.harchivos dependiendo del objetivo.

Los números de syscall apropiados para un programa de 64 bits están en asm/unistd_64.h, y aquellos para un programa de 32 bits en asm/unistd_32.h(o la _x32.hvariante casi equivalente ). Los dos son diferentes porque las arquitecturas de 32 y 64 bits son, de hecho, sistemas operativos completamente diferentes. Comparten el mismo conjunto de llamadas al sistema, pero no en el mismo orden, por varias razones.

La mayoría de estos también tienen envoltorios de lenguaje C, por lo que rara vez necesitará usarlos syscall(2)directamente.


1 Y porque no sé para qué sirve.


0

Para agregar todas las excelentes respuestas, hay una utilidad ausyscallque se puede utilizar para enumerar todas las llamadas al sistema y sus asignaciones de enteros para la arquitectura particular.

p.ej:

$ ausyscall --dump
Using x86_64 syscall table:
0   read
1   write
2   open
3   close
4   stat
...
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.