[Notas de lectura] Diseño del kernel de Linux y llamada al sistema de implementación

La implementación de la interfaz de la llamada del sistema es principalmente para asegurar la estabilidad y confiabilidad del sistema y para evitar la aplicación arbitraria de la aplicación.

1. Comunicación nuclear de Yonai

Las llamadas al sistema agregan una capa intermedia entre los procesos de espacio de usuario y los dispositivos de hardware.
El papel es el siguiente:

  1. Proporciona una interfaz abstracta de hardware para espacio de usuario;
  2. Garantizar la estabilidad y seguridad del sistema;
  3. Cada proceso se ejecuta en un sistema virtual y proporciona una interfaz tan común en el espacio del usuario y el resto del sistema.

ps: en los sistemas Linux, las llamadas al sistema son el único medio de acceso de espacio de usuario al kernel; a excepción de las excepciones y las trampas, son el único punto de entrada legal para el kernel.

2. Bibliotecas API, POSIX y C

En general, las aplicaciones se programan a través de interfaces de programación de aplicaciones (API) implementadas en el espacio del usuario en lugar de hacerlo directamente a través de llamadas al sistema.
ps: las aplicaciones que usan esta interfaz de programación en realidad no necesitan corresponder a las llamadas del sistema proporcionadas por el núcleo.

Como se muestra en la figura para profundizar la comprensión:
Inserte la descripción de la imagen aquí
existe una máxima sobre el diseño de interfaz de unix " proporcionar mecanismo (qué funciones deben proporcionar) en lugar de estrategia (cómo lograr estas funciones) ". Es decir, el sistema Unix llama a funciones abstractas para lograr un propósito determinado. En cuanto a cómo usar estas funciones, el núcleo no necesita preocuparse en absoluto.

3. Llamada del sistema

Para acceder a la llamada al sistema (a menudo llamada syscall en Linux), generalmente a través de la llamada a la función definida en la biblioteca C.
Cuando se produce un error de llamada del sistema, la biblioteca C escribirá el código de error en la variable global errno. Esta variable se puede traducir a una cadena de error que el usuario puede entender llamando a la función de biblioteca oerror ().

P: ¿Cómo definir la llamada al sistema?
R: Para garantizar la compatibilidad de los sistemas de 32 bits y 64 bits, las llamadas al sistema tienen diferentes tipos de valores de retorno en el espacio del usuario y en el espacio del kernel, int en el espacio del usuario y largos en el espacio del kernel. El nombre de la función también tiene el prefijo sys_. Por ejemplo, la llamada al sistema getpid () se define como sys_getpid () en el núcleo.

3.1 Función de llamada al sistema correspondiente al número de llamada del sistema

En Linux, cada llamada al sistema recibe un número de llamada al sistema (único).
Cuando un proceso en el espacio de usuario ejecuta una llamada del sistema, el número de llamada del sistema se utiliza para indicar qué llamada del sistema se va a ejecutar. El proceso no menciona el nombre de la llamada del sistema (por lo que el número de la llamada del sistema es importante).

Linux tiene un sistema "no implementado" llamado sys_ni_syscall (), que no hace nada más que devolver -ENOSYS.

El núcleo registra una lista de todas las llamadas al sistema registradas en la tabla de llamadas del sistema y las almacena en sys_call_table. Esta tabla especifica un número de llamada de sistema único para cada llamada de sistema válida.

3.2 Rendimiento de las llamadas al sistema.

Las llamadas al sistema Linux se ejecutan más rápido que muchos otros sistemas operativos.
¿Por qué
R: Linux es corto de tiempo el cambio de contexto es una razón importante, y fuera del núcleo han sido optimizados para ser simple y eficiente;
seguido por el gestor de llamadas del sistema y cada llamada al sistema en sí es muy simple.

4. Sistema de manejo de llamadas

Los programas de espacio de usuario no pueden ejecutar directamente el código del núcleo.
La aplicación debe notificar al sistema de alguna manera y dejar que el núcleo realice llamadas del sistema en el espacio del núcleo en nombre de la aplicación.
El mecanismo para notificar al núcleo se implementa mediante interrupciones suaves : al generar una excepción, el sistema cambia al estado del núcleo para ejecutar el controlador de excepciones: el controlador de llamadas del sistema.

4.1 Especifique la llamada al sistema apropiada

Debido a que todas las llamadas al sistema caen en el kernel de la misma manera, no es suficiente caer en el espacio del kernel. El número de llamada del sistema debe pasarse al núcleo.
Inserte la descripción de la imagen aquí

4.2 Paso de parámetros

Además del número de llamada del sistema, la mayoría de las llamadas del sistema también requieren una entrada de parámetros externos. Por lo tanto, cuando ocurre una trampa, estos parámetros deben pasarse del espacio del usuario al kernel. La forma más fácil es almacenar estos parámetros en el registro como pasar el número de llamada del sistema.

5. Implementación de la llamada al sistema.

5.1 Implementando llamadas al sistema

El primer paso para implementar una nueva llamada al sistema es determinar su propósito. Cada llamada al sistema debe tener un propósito claro. No se recomienda usar llamadas de sistema multipropósito en Linux (una llamada de sistema elige completar diferentes tareas pasando valores de parámetros diferentes).

5.2 Verificación de parámetros

Las llamadas al sistema deben verificar cuidadosamente si todos sus parámetros son legales y válidos . Evitar que los usuarios pasen entradas ilegales al kernel.
Cada parámetro debe verificarse para garantizar que no solo sean válidos y válidos, sino que también sean correctos. Un proceso no debe permitir que el núcleo acceda a recursos a los que no tiene acceso.
El tipo de verificación más importante es verificar si el puntero proporcionado por el usuario es válido.
Antes de recibir un puntero de espacio de usuario, el núcleo debe garantizar lo siguiente:

  1. El área de memoria señalada por el puntero pertenece al espacio del usuario. El proceso no debe convencer al núcleo para que lea los datos en el espacio del núcleo;
  2. El área de memoria señalada por el puntero está en el espacio de direcciones del proceso. Los procesos no deben engañar al núcleo para leer datos de otros procesos;
  3. Si se lee, la memoria debe marcarse como legible; si está escrita, la memoria debe marcarse como grabable; si es ejecutable, la memoria debe marcarse como ejecutable. Los procesos no deben omitir las restricciones de acceso a la memoria.

El núcleo proporciona dos métodos para completar las verificaciones necesarias y copiar datos de un lado a otro entre el espacio del núcleo y el espacio del usuario. Como se muestra en la siguiente tabla:

Método Función Explicación Valor de retorno
copy_to_user () Escribir datos en el espacio del usuario El primer parámetro es la dirección de memoria de destino en el espacio del proceso, el segundo es la dirección de origen en el espacio del kernel y el último parámetro es la longitud de los datos que se copiarán (número de bytes) Error de ejecución: el número de bytes de datos que no se pudieron copiar; éxito: 0; cuando se produce el error anterior, la llamada del sistema devuelve el estándar -EFALTO
copy_from_user () Leer datos del espacio del usuario También hay tres parámetros, similares a copy_to_user, los datos en la posición especificada por el segundo parámetro se copian en la posición especificada por el primer parámetro, y la longitud de los datos copiados se determina por el tercer parámetro Igual que el anterior

ps: tanto copy_to_user () como copy_from_user () pueden causar el bloqueo. Cuando las páginas que contienen datos del usuario se intercambian en el disco duro en lugar de en la memoria física, se produce el bloqueo. En este punto, el proceso se suspenderá hasta que el controlador de fallas de página devuelva la página del disco duro a la memoria física.

El último cheque es por autoridad legal .
La nueva versión del kernel de Linux proporciona un mecanismo de "capacidad" más detallado, y el nuevo sistema permite verificar permisos especiales para recursos específicos. La persona que llama puede usar la función enable () para verificar si tiene derecho a operar en el recurso especificado.Si devuelve un valor distinto de cero, la persona que llama tiene derecho a realizar la operación y devuelve 0 para no tener derecho a operar.
por ejemplo:

if(!capable(CAP_SYSY_BOOT))	/* 启动系统的系统管理员 */
	return -EPERM;

Consulte <linux / capacity.h> para obtener una lista de las capacidades de propiedad y sus permisos.

6. Contexto de llamada del sistema

El núcleo está en el contexto del proceso cuando ejecuta llamadas al sistema. El puntero actual apunta a la tarea actual, el proceso que provocó la llamada al sistema.

En el contexto del proceso , el núcleo puede dormir (como cuando se bloquea una llamada del sistema o cuando se llama explícitamente a schedule ()) y se puede evitar .

6.1 El paso final de vincular una llamada al sistema

P: Después de escribir una llamada al sistema, ¿cómo registrarla como una llamada formal al sistema?
A:

  1. Agregue una entrada al final de la tabla de llamadas del sistema (para la mayoría de las arquitecturas, esta tabla se encuentra en el archivo entry.s). Cada sistema de hardware que admite la llamada del sistema debe hacer este tipo de trabajo. A partir de 0, la posición de la llamada del sistema en esta tabla es su número de llamada del sistema;
  2. Para varias arquitecturas compatibles, el número de llamada del sistema debe definirse en <asm / unistd.h>, y el hábito de llamar a buenos comentarios generalmente se agrega cada 5 entradas en el archivo, que se puede encontrar en la llamada del sistema correspondiente. Para proporcionar comodidad al llamar
  3. Las llamadas al sistema deben compilarse en la imagen del kernel (no pueden compilarse en módulos). Simplemente colóquelo en un archivo relevante en kernel /, como sys.c, que contiene varias llamadas al sistema.

6.2 Acceso a llamadas del sistema desde el espacio del usuario - Biblioteca C / Macro de Linux

Por lo general, las llamadas al sistema son compatibles con la biblioteca C. Al incluir archivos de encabezado estándar y vincularlos con la biblioteca C, los programas de usuario pueden usar llamadas del sistema (o funciones de la biblioteca de llamadas, que en realidad son llamadas por las funciones de la biblioteca).
Linux en sí mismo proporciona un conjunto de macros para el acceso directo a las llamadas del sistema (no es necesario introducir archivos de encabezado de biblioteca C), configurará registros e instrucciones de captura de llamadas.
Estas macros son _syscalln (), donde n varía de 0 a 6, lo que representa el número de parámetros que deben pasarse a la llamada al sistema. Esto se debe a que la macro debe saber cuántos parámetros se introducen en el registro en qué orden.
Por ejemplo: la
definición de llamada al sistema de open () es:

long open(const char *filename, int flags, int mode);

Sin el soporte de la biblioteca C, la forma de llamada directa a través de la macro es:

#define NR_open 5		/* <asm/unistd.h>中定义的系统调用号 */
_syscall3(long, open, const char*, filename, int, flags, int, mode)  

Para cada macro, hay 2 + 2xn parámetros.
El primer parámetro corresponde al tipo de valor de retorno de la llamada al sistema.
El segundo parámetro es el nombre de la llamada al sistema.
El siguiente es el tipo y el nombre de cada parámetro organizado en el orden de los parámetros de llamada del sistema.

6.3 ¿Por qué no usar la llamada al sistema?

Los sistemas Linux intentan evitar simplemente agregar una nueva llamada al sistema cada vez que aparece una nueva abstracción.
Por lo general, reemplace la llamada al sistema que desea implementar de la siguiente manera:
implemente un nodo de dispositivo e implemente read () y write () para esto. Use ioctl para operar en configuraciones específicas o recuperar información específica.

  1. Algunas interfaces, como los semáforos, se pueden representar mediante descriptores de archivo, por lo que se pueden operar como se describe anteriormente;
  2. Coloque la información agregada como un archivo en una ubicación adecuada en sysfs.
91 artículos originales publicados · 17 elogiados · 50,000+ vistas

Supongo que te gusta

Origin blog.csdn.net/qq_23327993/article/details/105382862
Recomendado
Clasificación