Cómo agregar llamadas al sistema en el kernel de Linux
Agregué una nueva llamada al sistema para el kernel linux0.11 en bochs2.2.1. Los pasos son los siguientes:
1./. usr/src/linux/include/unistd.h Agregue: #define __NR_ mytest 87
Luego declare el siguiente prototipo de función: int mytest();
2./usr/src /linux/include/linux/sys.h Agregar: extern int sys_mytest();
Luego agregue sys_mytest en la tabla sys_call_
3. Agregue la siguiente implementación de función a kernel/sys.c:
int sys_mytest(){
printk("¡Esto es una prueba!";
return); 123 ;
}
4.
4. Agregue 1 al número de llamada del sistema en /usr/src/linux/kernel/system_call.s (original). Era 86, ahora es 87)
5. Luego compila el kernel en /usr/src/linux make clean; make Image
6. p> 6. cp /usr/src/linux/include/unistd.h /usr/include/unistd.h
7. Restablecer bochs
8. Generar archivo test.c
El archivo 9.c es el siguiente:
#define __LIBRARY__
#include
_syscall0 (int,miprueba)
int main(){
int a
a = miprueba(); a = miprueba ();
printf("%d", a);
return 0;
}
9.
9. Luego compile gcc test.c y ejecute a.out. Los pasos anteriores pasaron, pero cada llamada devuelve -1. Luego verifiqué que errno es 1 (lo que indica que la operación no está permitida). No sé por qué.
Los expertos que conocen el sistema dirán ¡gracias! ¡Este problema me ha preocupado durante mucho tiempo!
2. Agregar llamadas al sistema al nuevo kernel de Linux
Cómo agregar nuevas llamadas al sistema al sistema Linux
Las llamadas al sistema son aplicaciones y sistemas operativos Interfaces funcionales entre núcleos. Su objetivo principal es permitir a los usuarios utilizar las funciones proporcionadas por el sistema operativo relacionadas con la gestión de dispositivos, sistema de entrada/salida, sistema de archivos y control de procesos, comunicación y gestión de almacenamiento sin conocer la estructura interna del programa del sistema y los detalles del hardware relacionado Reduzca la carga de los usuarios, proteja el sistema y mejore la utilización de recursos.
Como representante del software libre, el excelente rendimiento del sistema operativo Linux lo hace cada vez más utilizado no sólo entre los profesionales, sino también en pleno apogeo en los negocios. En Linux, la mayoría de las llamadas al sistema están contenidas en la biblioteca libc de Linux, y estas llamadas al sistema se pueden llamar a través de métodos de llamada de funciones estándar de C. Entonces, para los entusiastas de Linux, ¿cómo agregar nuevas llamadas al sistema en Linux?
1 mecanismo de llamada al sistema Linux
En Linux, las llamadas al sistema se implementan como tipos de excepción.
Ejecutará las instrucciones de código de máquina correspondientes para generar la señal de excepción. El impacto importante de una interrupción o excepción es que el sistema cambiará automáticamente el modo de usuario al modo kernel para su procesamiento.
Int $0x80
Esta instrucción transfiere el control al núcleo utilizando el vector de interrupción/excepción 128 (es decir, 80 hexadecimal). Para lograr el objetivo de utilizar llamadas al sistema sin tener que programar con instrucciones de máquina, se proporciona una breve sección de subrutina en la biblioteca C estándar para cada llamada al sistema, que se utiliza para completar el trabajo de programación en código de máquina. De hecho, los segmentos del código de máquina son muy cortos. Todo lo que tiene que hacer es cargar los parámetros de la llamada al sistema en un registro de la CPU y luego ejecutar la instrucción int $0x80. Luego se ejecuta la llamada al sistema, el valor de retorno de la llamada al sistema se coloca en un registro de la CPU y una subrutina de biblioteca estándar recibe el valor de retorno y lo envía de regreso al programa de usuario.
Para simplificar la ejecución de las llamadas al sistema, Linux proporciona un conjunto de macros de preprocesador. Se pueden utilizar dentro del programa. Estas macros aceptan ciertos parámetros y luego los expanden para llamar a una función para invocar la llamada al sistema especificada.
El formato de nombre de estas macros es similar al siguiente:
_syscallN(parameters)
Donde N es el número de parámetros necesarios para la llamada al sistema, y los parámetros son un conjunto de parámetros. Estos parámetros permiten que la macro realice expansiones apropiadas para llamadas específicas al sistema. Por ejemplo, para crear una función que llame a la llamada al sistema setuid(), utilice:
_syscall1(int, setuid, uid_t, uid )
El primer argumento de syscallN( ) macro int indica que el tipo de valor de retorno de la función generada es un número entero, y el segundo parámetro setuid indica el nombre de la función generada. A esto le sigue cada parámetro requerido por la llamada al sistema. Hay dos parámetros después de esta macro, a saber, uid_t y uid, que especifican el tipo y el nombre del parámetro respectivamente.
Además, existen restricciones sobre los tipos de datos que se pueden utilizar como parámetros de llamada al sistema; no pueden exceder los 4 bytes de tamaño. Esto se debe a que cuando se ejecuta la instrucción int $0x80 para una llamada al sistema, todos los valores de los parámetros se encuentran en registros de CPU de 32 bits. Otra limitación del uso de registros de CPU para pasar argumentos es la cantidad de argumentos que se pueden pasar a una llamada al sistema. El límite es que se pueden pasar un máximo de 5 parámetros. Por lo tanto, Linux I*** define seis instrucciones macro _syscallN() diferentes, desde _syscall0(), _syscall1() hasta _syscall5().
Una vez que la macro _syscallN() se expande con los parámetros apropiados para una llamada al sistema específica, se produce una función con el mismo nombre que la llamada al sistema, que ejecuta la llamada al sistema en el programa de usuario.
2 Agregar una nueva llamada al sistema
Si los usuarios desean agregar una nueva llamada al sistema en Linux, deben seguir varios pasos para agregarla correctamente. Los siguientes pasos introducirán la adición de un sistema. Llame en detalle ¿Qué implica?
(1) Agregar código fuente
La primera tarea es escribir el programa fuente que se agregará al kernel, es decir, la función que se agregará al archivo del kernel. El nombre del archivo debe tener como prefijo el nuevo nombre de llamada del sistema con el indicador sys_. Suponiendo que la llamada al sistema recién agregada es mycall(int number), agregue el código fuente al archivo /usr/src/linux/kernel/sys.c de la siguiente manera:
asmlinkage int sys_mycall(int number )
{
número de retorno;
}
Como ejemplo más simple, nuestra llamada al sistema recién agregada simplemente devuelve un valor entero.
(2) Conectar nuevas llamadas al sistema
Después de agregar una nueva llamada al sistema, la siguiente tarea es informar a otras partes del kernel de Linux sobre la existencia del programa. Para agregar conexiones a nuevas funciones desde un programa del kernel existente, es necesario editar dos archivos.
En la versión del kernel de Linux que utilizamos (RedHat 6.0, kernel 2.2.5-15), el primer archivo que hay que modificar es:
/usr/src/linux/ include/asm-i386/unistd.h
Este archivo contiene una lista de llamadas al sistema, asignando un número único a cada llamada al sistema. Cada línea del archivo tiene el siguiente formato:
#define __NR_name NNN
donde nombre se reemplaza con el nombre de la llamada al sistema y NNN es el número correspondiente a la llamada al sistema. El nuevo nombre de llamada del sistema debe agregarse al final de la lista y asignarse al siguiente número de llamada del sistema disponible en la secuencia de numeración. Nuestra llamada al sistema es la siguiente:
#define __NR_mycall 191
El número de llamada del sistema es 191. La razón por la que es 191 es porque el propio kernel Linux-2.2 ya usa 190 como el número de llamada del sistema.
El segundo archivo a modificar es:
/usr/ src/linux/arch/i386/kernel/entry.S
Lista de archivos Algo similar a lo siguiente:
.long SYMBOL_NAME()
Esta lista se utiliza para inicializar la matriz sys_call_table[]. Esta matriz contiene punteros a cada llamada al sistema en el kernel. Esto agregará un puntero a la nueva función del núcleo a la matriz. Agregamos una línea al final de la lista:
.long SYMBOL_NAME(sys_mycall)
(3) Reconstruir el nuevo kernel de Linux
Para hacer La nueva llamada al sistema entra en vigor. Es necesario reconstruir el kernel de Linux. Esto requiere iniciar sesión como superusuario.
#pwd
/usr/src/linux
#
El superusuario está en el directorio de trabajo actual (/usr/ src/linux ) para reconstruir el kernel.
#make config
#make dep
#make clearn
#make bzImage
Después de la compilación completado, el sistema generará un archivo de imagen del kernel comprimido, que se puede utilizar para la instalación:
/usr/src/linux/ arch/i386/boot/bzImage
(4) Arrancar con el nuevo sistema kernel
Para utilizar las nuevas llamadas al sistema, es necesario reiniciar el sistema con un nuevo kernel reconstruido.
Para hacer esto, es necesario modificar el archivo /etc/lilo.conf en nuestro sistema, su contenido es el siguiente:
boot=/dev/hda
map=/. boot/map
install=/boot/boot.b
rompt
timeout=50
image=/boot/vmlinuz- 2.2.5- 15
label=linux
root=/dev/hdb1
solo lectura
other=/dev/ hda1
label=dos
table=/dev/had
Primero edite el archivo para agregar el nuevo kernel de arranque:
imagen =/boot/bzImage- new
label=linux-new
root=/dev/hdb1
solo lectura
Después agregando, el archivo se ve así:
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
prompt
timeout= 50
image=/boot/bzImage-new
label=linux-new
root=/dev/hdb1
solo lectura
image=/boot/vmlinuz-2.2.5-15
label=linux
root=/dev/ hdb1
solo lectura
other=/dev/hda1
label=dos
tabla =/dev/hda
De esta manera, la nueva imagen del kernel bzImage-new se convierte en el kernel de arranque predeterminado. Para utilizar el nuevo archivo de configuración lilo.conf, también se debe ejecutar el siguiente comando:
#cp /usr/src/linux/arch/i386/boot/zImage /boot/bzImage-new
En segundo lugar configura lilo:
# /sbin/lilo
Ahora, al reiniciar el sistema, hay tres opciones después del mensaje de inicio: linux-new, linux , dos, nuevo El kernel se convertirá en el kernel de arranque predeterminado.
En este punto, se ha creado un nuevo kernel de Linux y las llamadas al sistema recién agregadas se han convertido en parte del sistema operativo. Reiniciar Linux permite a los usuarios utilizar llamadas al sistema en las aplicaciones.
(5) Utilice la nueva llamada al sistema
Utilice la nueva llamada al sistema mycall en su aplicación. Nuevamente, con fines experimentales, escribimos un ejemplo simple xtdy.c.
/* xtdy.c */
#include
_syscall1( int, mycall ,int,ret)
main()
{
printf("%d \n",mycall(100)); p> p>
}
Compila este programa:
# cc -o xtdy xtdy.c
Ejecuta:
# xtdy
Resultado:
# 100
Tenga en cuenta que debido al uso de llamadas al sistema, el usuario debe ser el superusuario al compilar y ejecutar el programa.