Agregar
una nueva llamada al sistema al kernel de linux 3.2.2 para un CPU x86 de 32 bits 12I, enero 2012 |
Introducción El presente documento es una
guía simplificada para agregar una llamada al sistema en el
kernel de linux
versión 3.2.2. Una llamada al sistema es utilizada por una
aplicación
(programa de usuario) para solicitarle un servicio al sistema
operativo.... más información en la clase y notas de curso
|
Requerimientos Se recomienda tener experiencia
en la compilación del kenel de linux. Por ejemplo, se
podría haber compilado el kernel para soportar
directamente el sistema de archivos ext3 o ext4.
Por supuesto, es necesario tener las fuentes del kernel de linux. |
Archivos a modificar/crear Las siguientes rutas son relativas a
/usr/src/linux. La ruta
anterior
podría ser un enlace simbólico a la ruta /usr/src/linux-3.2.2
#vim arch/x86/kernel/syscall_table_32.S #vim arch/x86/include/asm/unistd_32.h #vim arch/x86/include/asm/syscalls.h Archivo en el espacio de usuario, para realizar la llamada al sistema: $vim som_llamada.c |
Tabla de
llamadas al sistema
El archivo arch/x86/kernel/syscall_table_32.S contiene la tabla de las llamadas al sistema, la cual consiste en la definición de sus nombres. El número de la llamada se da de manera implicita de acuerdo a su posición en la tabla. Agregamos al final de la tabla el nombre de nuestra llamada utilizando el mismo formato: ENTRY(sys_call_table) .long sys_restart_syscall .long sys_exit ... ... .long sys_process_vm_writev /*348*/ .long sys_sumar /*349, nueva llamada*/ La llamada al sistema que implementaremos será la suma de dos parámetros enteros. |
Asociación de tabla y funciones Para asociar una entrada de la tabla
anterior con una función, es necesario definir un
símbolo. La tabla de asociación se encuentra en el
archivo arch/x86/include/asm/unistd_32.h en el cual se puede apreciar la
definición de nombres y números. De igual forma agregamos
la definición nuestra llamada:
... #define __NR_restart_syscall 0 #define __NR_exit 1 ... #define __NR_process_vm_writev 348 #define __NR_sumar 349 El tamaño de la tabla está definido en el mismo archivo con el símbolo: #define __NR_syscalls 349 y evidentemente cambiamos por: #define __NR_syscalls 350 |
Definición
de la llamada El archivo que contendrá la
definición de la llamada dependerá de lo que hace la
misma llamada, es decir, si es una llamada relacionada con el tiempo
deberá de estar en el kernel/time.c. Si la llamada tiene que ver con el
acceso a procesos podría estar en kernel/sched.c.
Las llamadas genéricas se definen en el archivo kernel/sys.c. A patir de la versión 3.0 del kernel, las definiciones se crean por medio de interfaces constantes. La interfaz sirve para ejecutar las llamadas de manera similar a como lo hace la llamada al sistema execve. Con una interfaz constante, cada arquitectura crea su propia interfaz y llama a una sola implementación de la llamada. La interfaz para el x86 se puede ver en el archivo arch/x86/kernel/sys_i386_32.c, dicha interfaz se llama kernel_execve. La definición real de la llamada se puede hacer en el archivo kernel/sys.c. Se han creado 3 tipos de interfaz de acuerdo con el número de parámetros que requiera la llamada a implementar. Como nuestra llamada tendrá dos parámetros utilizamos la interfaz SYSCALL_DEFINE2, de la siguiente forma: SYSCALL_DEFINE2(sumar,int,a,int,b) { return a + b; } Se observa que el primero parámetro es el nombre de la llamada, y los siguientes es tanto el tipo de dato del parámetro como el identificador. |
Compilación del kernel Procedemos
a compilar el kernel. Es importante recordar que es necesario tener un
archivo de configuración para compilar el kernel, es decir, un
archivo .config.
Puedes utilizar la configuración del kernel que está en
ejecución. Para detalles ver la compilación
del kernel.
#uname -a Linux drmoriarti 2.6.32-5-686 #1 SMP Thu Nov 3 04:23:54 UTC 2011 i686 #cp /boot/config-2.6.32-5-686 .config Si se han utilizado las fuentes para compilar un kernel anterior, es necesario primero ejecutar el comando: #make clean Y mientras se compila, ya sabes, un cafecito. Por cierto el chango (el Isaac) recomienda que prueben el café de origen de la Finca de Jocutla. |
Prueba en un programa de usuario Finalmente, lanzamos nuestro nuevo
kernel y lo probamos invocando nuestra llamada desde un programa de
usuario, som_llamada.c:
#include<linux/unistd.h> int
main() printf(“1+2 = %d\n”, syscall(349, 1, 2)); return 0; } |