Es importante tener en cuenta que la programación del kernel difiere significativamente de la programación del espacio de usuario. El núcleo es una entidad independiente, que no puede usar bibliotecas de espacio de usuario, incluso libc en Linux o kernel32.dll en Windows. Como resultado, las funciones habituales utilizadas en el espacio de usuario (printf, malloc, free, open, read, write, memcpy, strcpy, etc.) ya no se pueden utilizar.
En conclusión, la programación del kernel se basa en una API completamente nueva e independiente que no está relacionada con la API en el espacio de usuario, ya sea que nos refiramos a POSIX , Win32 o ANSI C. Una diferencia importante en la programación del kernel es cómo acceder a él. y asignación de memoria. Debido al hecho de que la programación del kernel se realiza a un nivel muy cercano a la máquina física, existen reglas importantes con respecto a la administración de la memoria.
Primero, funciona con varios tipos de memoria: – memoria física – memoria virtual en el espacio de direcciones del núcleo – memoria virtual del espacio de direcciones de un proceso – memoria residente – sabemos con certeza que las páginas a las que se accede están presentes en la memoria física
La memoria virtual en el espacio de direcciones de un proceso no puede considerarse residente debido a los mecanismos de memoria virtual implementados por el sistema operativo: las páginas pueden estar en el intercambio, o pueden no estar presentes en la memoria física como resultado del mecanismo de paginación de solicitudes.
La memoria en el espacio de direcciones del kernel puede o no ser residente. Tanto los segmentos de datos como de código de un módulo y la pila del kernel de un proceso son residentes.
La memoria dinámica puede o no ser residente, dependiendo de cómo se asigne. Cuando se trabaja con memoria residente, las cosas son simples: se puede acceder a la memoria en cualquier momento. Sin embargo, si se trabaja con memoria no residente, solo se puede acceder a ella desde determinados contextos.
Memoria no residente solo se puede acceder desde el contexto del proceso. Acceder a la memoria no residente desde el contexto de interrupción tiene resultados impredecibles y, por lo tanto, cuando el sistema operativo detecta dicho acceso, tomará medidas drásticas: bloquear o reiniciar el sistema, para evitar daños graves.
La memoria virtual de un proceso no se puede acceder directamente desde el kernel. Generalmente, está totalmente desaconsejado acceder al espacio de direcciones de un proceso, pero hay situaciones en las que un controlador de dispositivo tiene que hacerlo. El caso típico es donde el controlador del dispositivo tiene que acceder a un búfer desde el espacio de usuario. En este caso, el controlador del dispositivo debe usar funciones especiales y no acceder directamente al búfer. Esto es necesario para evitar el acceso a áreas de memoria no válidas.
Otra diferencia de la programación en espacio de usuario, relativa al trabajo con memoria, se debe a la pila, la pila cuyo tamaño es fijo y limitado. En el kernel de Linux, se usa una pila de 4K de forma predeterminada, y en Windows, se usa una pila de 12K. Por este motivo, se debe evitar la asignación de grandes estructuras en la pila o el uso de llamadas recursivas.
Con respecto al modo de ejecución en el núcleo, distinguimos dos contextos: contexto de proceso y contexto de interrupción. Estamos en el contexto del proceso cuando ejecutamos código después de una llamada al sistema o cuando ejecutamos en el contexto de un subproceso del núcleo. Cuando estamos ejecutando en la rutina de tratar con un descanso o una acción diferida, estamos ejecutando en un contexto de descanso.
Una de las características más importantes de la programación del kernel es el paralelismo. Tanto Linux como Windows admiten sistemas SMP con múltiples procesadores, pero también el kernel admite de manera preventiva múltiples procesadores. Esto hace que la programación del núcleo sea más difícil porque el acceso a las variables globales debe sincronizarse con primitivos de bloqueo o de bloqueo.
Tanto Linux como Windows usan núcleos preventivos. La noción de multitarea preventiva no debe confundirse con la noción de núcleo preventivo. La noción de multitarea preventiva se refiere al hecho de que el sistema operativo interrumpe la ejecución de un proceso de forma forzada, cuando ha expirado la cantidad de tiempo y se ejecuta en el espacio de usuario, para ejecutar otro proceso. Para la programación en el Kernel de Linux, la convención utilizada para llamar a las funciones para indicar el éxito es idéntica a la de la programación UNIX: 0 para el éxito o un valor distinto de 0 para el fracaso.