linux - que - pila de kernel y pila de espacio de usuario
que es el kernel (2)
¿Cuál es la diferencia entre la pila del kernel y la pila del usuario? ¿Por qué se usa la pila kernel? Si se declara una variable local en un ISR, ¿dónde se almacenará? ¿Cada proceso tiene su propia pila de kernel? Entonces, ¿cómo se coordina el proceso entre estas dos pilas?
- ¿Cuál es la diferencia entre la pila del kernel y la pila del usuario?
En resumen, nada, aparte de usar una ubicación diferente en la memoria (y por lo tanto un valor diferente para el registro stackpointer), y generalmente diferentes protecciones de acceso a la memoria. Es decir, cuando se ejecuta en modo de usuario, la memoria del kernel (parte de la cual es la pila del kernel) no será accesible aunque esté mapeada. A la inversa, sin que el código del kernel lo solicite explícitamente (en Linux, a través de funciones como copy_from_user()
), la memoria del usuario (incluida la pila del usuario) no suele ser accesible directamente.
- ¿Por qué se usa [una pila de kernel por separado]?
Separación de privilegios y seguridad. Por un lado, los programas de espacio de usuario pueden hacer que su pila (puntero) sea lo que quieran, y generalmente no existe ningún requisito arquitectónico para tener uno válido. Por lo tanto, el kernel no puede confiar en que el stackpointer del espacio de usuario sea válido ni utilizable, y por lo tanto requerirá un conjunto bajo su propio control. Diferentes arquitecturas de CPU implementan esto de diferentes maneras; Las CPU x86 cambian automáticamente los stacks de pila cuando se producen conmutadores de modo privilegio, y los valores que se utilizarán para diferentes niveles de privilegios son configurables, por código privilegiado (es decir, solo el kernel).
- Si se declara una variable local en un ISR, ¿dónde se almacenará?
En la pila del kernel. El kernel (kernel de Linux) no enlaza los ISR directamente a las puertas de interrupción de la arquitectura x86 sino que delega el despacho de interrupción a un mecanismo común de entrada / salida de interrupción del kernel que guarda el estado del registro previo a la interrupción antes de llamar al manejador registrado. . La CPU al despachar una interrupción podría ejecutar un privilegio y / o un interruptor de pila, y el núcleo lo usa / configura para que el código de entrada de interrupción común ya pueda contar con la presencia de una pila de kernel.
Dicho esto, las interrupciones que ocurran mientras se ejecuta el código kernel simplemente (continuarán) usarán la pila kernel en su lugar en ese punto. Esto puede, si los manejadores de interrupción tienen rutas de llamada anidadas profundamente, conducen a desbordamientos de pila (si se interrumpe una ruta profunda de kernel y el manejador causa otra ruta profunda; en Linux, el código de red / sistema de software RAID interrumpido por el código de red con iptables activo es se sabe que desencadena esto en núcleos más antiguos no afinados ... la solución es aumentar los tamaños de la pila del kernel para tales cargas de trabajo).
- ¿Cada proceso tiene su propia pila de kernel?
No solo cada proceso: cada hilo tiene su propia pila de kernel (y, de hecho, también su propia pila de usuarios). Recuerde que la única diferencia entre procesos e hilos (para Linux) es el hecho de que múltiples hilos pueden compartir un espacio de direcciones (formando un proceso).
- ¿Cómo se coordina el proceso entre estas dos pilas?
Para nada, no es necesario. La programación (cómo y cuándo se están ejecutando diferentes subprocesos, cómo se guarda y restaura su estado) es la tarea del sistema operativo y los procesos no tienen que preocuparse por esto. A medida que se crean hilos (y cada proceso debe tener al menos un hilo), el núcleo crea pilas de kernel para ellos, mientras que las pilas de espacios de usuario se crean / proporcionan explícitamente según el mecanismo utilizado para crear un hilo (funciones como makecontext()
o pthread_create()
permite que el que llama especifique una región de memoria para ser utilizada para la pila del hilo "secundario") o heredado (mediante clonación de memoria en acceso, generalmente llamada "copiar en escritura" / COW, al crear un nuevo proceso).
Dicho esto, el proceso puede influir en la programación de sus hilos y / o influir en el contexto (estado, entre los que se encuentra el stackpointer del hilo). Hay varias formas de setcontext()
: señales de UNIX, setcontext()
, pthread_yield()
/ pthread_cancel()
, ... - pero esto está desacreditando un poco de la pregunta original.
Mi respuesta se recoge de otras preguntas SO con mis cosas.
What''s the difference between kernel stack and user stack?
Como programador de kernel, usted sabe que el kernel debe estar restringido de programas de usuario erróneos. Supongamos que mantiene la misma pila tanto para el kernel como para el espacio de usuario, y luego la simple segfault en la aplicación de usuario bloquea el núcleo y necesita reiniciarse.
Hay una "pila de kernel" por CPU como ISR Stack y una "pila de kernel" por Process. Hay una "pila de usuario" para cada proceso, aunque cada subproceso tiene su propia pila, incluidos los subprocesos del usuario y del núcleo.
http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-10/3194.html
Why kernel stack is used?
Por lo tanto, cuando estamos en el modo núcleo, es necesario un tipo de mecanismo de pila para tratar las llamadas a funciones, variables locales similares al espacio del usuario.
http://www.kernel.org/doc/Documentation/x86/kernel-stacks
If a local variable is declared in an ISR, where it will be stored?
Se almacenará en la pila ISR (IRQSTACKSIZE). El ISR se ejecuta en una pila de interrupción separada solo si el hardware lo admite. De lo contrario, los cuadros de pila ISR se insertan en la pila de la secuencia interrumpida.
El espacio de usuario no sabe y, francamente, no le importa si la interrupción se sirve en la pila del kernel del proceso actual o en una pila ISR separada. Como las interrupciones vienen por cpu, por lo tanto ISR stack debe ser por cpu.
Does each process has its own kernel stack ?
Sí. Cada proceso tiene su propia pila de kernel.
Then how the process coordinates between both these stacks?
La respuesta de @ FrankH me parece genial.