Me gustaría entender el término "llamada al sistema". Estoy familiarizado con que las llamadas al sistema se utilizan para obtener servicios del núcleo de una aplicación de espacio de usuario.
La parte con la que necesito aclaración es la diferencia entre una "llamada al sistema" y una "implementación en C de la llamada al sistema".
Aquí hay una cita que me confunde:
En sistemas tipo Unix, esa API generalmente es parte de una implementación de la biblioteca C (libc), como glibc, que proporciona funciones de envoltorio para las llamadas del sistema, a menudo denominadas de la misma manera que las llamadas del sistema que llaman
¿Qué son las "llamadas al sistema que llaman"? ¿Dónde está su fuente? ¿Puedo incluirlos directamente en mi código?
¿Es la "llamada del sistema" en un sentido genérico solo una interfaz POSIX definida, pero para ver realmente la implementación, uno podría examinar la fuente C y ver cómo funciona realmente la comunicación del espacio de usuario al núcleo?
Nota de fondo: estoy tratando de entender si, al final, cada función c termina interactuando con dispositivos de /dev
.
fuente
getpid
llamada del sistema en el kernel de Linux: lxr.free-electrons.com/source/kernel/timer.c?v=2.6.35#L1337 . Y esta es la función de contenedor en la biblioteca estándar GNU C glibc-2.19: fossies.org/dox/glibc-2.19/… .Una llamada al sistema es una manera de pedirle a su sistema operativo (kernel) que realice alguna operación en nombre de su programa, que el programa no puede hacer por sí mismo (o simplemente es un inconveniente). La razón para no poder realizar alguna operación es normalmente que permitir que un programa aleatorio las haga puede comprometer la integridad del sistema, como hacer E / S (directamente a la RAM, sobrescribiendo cualquier cosa).
POSIX define una interfaz para programas, ciertas funciones que su programa puede llamar. Algunos de ellos se traducen más o menos directamente a las llamadas al sistema, otros requieren más elaboración. Es el tiempo de ejecución para su lenguaje, por ejemplo, la biblioteca C, que es responsable de ofrecer la interfaz POSIX, y de empaquetar argumentos y recibir los resultados de vuelta a la persona que llama.
Los sistemas Unixy ofrecen interfaces POSIX más o menos directamente como llamadas del sistema. Por lo general, hay una manera de invocar llamadas del sistema directamente, busque
syscall(2)
los detalles sobre cómo usar esta función en Linux.fuente
strlen
,strcpy
,sqrt
, yqsort
) puede ser y probablemente está en el espacio de usuario, cargado de una biblioteca. (Principalmente libc; funciones matemáticas comosqrt
y las funciones trigonométricas e hiperbólicas probablemente están en libm, la biblioteca matemática.)… (Continuación)fork
,kill
oopen
función, ya que estas requieren acceso al espacio del núcleo del sistema operativo de memoria (por ejemplo, la tabla de procesos) o instrucciones privilegiadas (por ejemplo, E / S). Por lo tanto, el código que realiza estas funciones debe estar en el núcleo del sistema operativo; por lo tanto, funciones del sistema o llamadas del sistema.Claro, vamos a hacer ¿cuántas-direcciones-podemos-mirar-a-este-elefante? cosa.
La llamada real del sistema es, en su programa integrado, la instrucción de la máquina que activa la escalada de privilegios al modo kernel, y en el núcleo mismo es el código que invoca la instrucción. El código libc (y cada tiempo de ejecución de idioma) configura los registros de la máquina y los parámetros en almacenamiento donde el código del núcleo espera encontrarlos, que pueden ser lugares decididamente extraños debido a restricciones en las instrucciones de esa máquina.
Una vez en el código del sistema operativo, hay un poco de desenrollado de imagen especular de las cosas específicas de la máquina que hizo el tiempo de ejecución del usuario y luego una llamada de subrutina perfectamente normal.
Si desea ver exactamente cómo funciona esto en un sistema operativo a gran escala, extraiga la fuente del núcleo (
git clone https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/
) y haga, por ejemplogit grep -i system\ call
. Tire de la fuente glibc y haga lo mismo.fuente
En Linux, al menos, el mecanismo de llamada del sistema funciona en la mayoría de las arquitecturas al colocar algunos datos con formato específico (generalmente algún tipo de estructura) en algunos registros o direcciones de memoria predefinidas.
Sin embargo, el problema surge al obligar a la CPU a hacer el cambio al espacio del kernel para que pueda ejecutar el código del kernel privilegiado para atender la llamada. Esto se hace forzando una falla de algún tipo (una falla que es una división entre 0, un desbordamiento indefinido o una falla predeterminada, etc.) que obliga al núcleo a asumir la ejecución para manejar la falla.
Normalmente, el kernel maneja las fallas al eliminar el proceso causante o al ejecutar un controlador proporcionado por el usuario. Sin embargo, en el caso de una llamada al sistema, en su lugar, verificará los registros predefinidos y las ubicaciones de memoria y, si contienen una solicitud de llamada al sistema, la ejecutará utilizando los datos proporcionados por el proceso del usuario en la estructura en memoria. Esto generalmente debe hacerse con un ensamblaje especialmente diseñado a mano y para facilitar el uso de la llamada al sistema para el usuario, la biblioteca C del sistema tiene que envolverlo como una función. Para obtener una interfaz de nivel inferior, visite http://man7.org/linux/man-pages/man2/syscall.2.html para obtener información sobre cómo funcionan las llamadas al sistema y cómo puede llamar sin un contenedor C.
Esto tiene una simplificación excesiva, no es cierto en todas las arquitecturas (mips tiene una instrucción especial de syscall) y no necesariamente funciona igual en todos los sistemas operativos. Aún así, si tiene algún comentario o pregunta, por favor pregunte.
Enmendado: Tenga en cuenta que, con respecto a su comentario sobre cosas en / dev /, esta es en realidad una interfaz de nivel superior para el núcleo, no una inferior. Estos dispositivos realmente usan (aproximadamente) 4 syscalls debajo. Escribirles es lo mismo que escribir una llamada al sistema, leer una llamada a la lectura, abrirlos / cerrarlos equivalentes a las llamadas al sistema abiertas y cerradas y ejecutar un ioctl provoca una llamada al sistema ioctl especial que en sí misma es una interfaz para acceder a una de las muchas ioctl del sistema llamadas (llamadas especiales, generalmente específicas del dispositivo con un uso demasiado limitado para escribir una llamada de sistema completa para ellas).
fuente
Cada llamada al sistema tiene un número entero asociado. Este número entero es una función del valor de retorno de la llamada al sistema, el número de argumentos a la llamada del sistema y el tipo de argumentos. Este número de llamada del sistema no es más que un desplazamiento en el vector de llamada del sistema global, este vector al que solo se puede acceder en modo privilegiado contiene un puntero a los controladores apropiados. El proceso al invocar una llamada al sistema, se generaría una interrupción de software (interrupción de captura), por lo tanto, se ejecutaría un controlador de trampa que determina qué llamada del sistema se debe invocar. Luego, el núcleo copiará los argumentos de la llamada al sistema pasada por el usuario que está en la pila en los registros del procesador, y al completar el servicio solicitado, los datos se volverán a copiar en la pila desde los registros del procesador. Esta es una de las razones por las cuales hay argumentos limitados para las llamadas al sistema,
fuente