Llamadas al sistema
- Obtener enlace
- X
- Correo electrónico
- Otras aplicaciones
Llamadas al sistema.-
Un Sistema Operativo multitarea en el que van a convivir un gran número de procesos. Es posible, bien por un fallo de programación o bien por un intento malicioso, que alguno de esos procesos haga cosas que atenten contra la estabilidad de todo el sistema. Por ello, con vistas a proteger esa estabilidad, el núcleo o kernel del sistema funciona en un entorno totalmente diferente al resto de programas. Se definen entonces dos modos de ejecución totalmente separados: el modo kernel y el modo usuario. Cada uno de estos modos de ejecución dispone de memoria y procedimientos diferentes, por lo que un programa de usuario no podrá ser capaz de dañar al núcleo.
Aquí se plantea una duda: si el núcleo del sistema es el único capaz de manipular los recursos físicos del sistema (hardware), y éste se ejecuta en un modo de ejecución totalmente disjunto al del resto de los programas, ¿cómo es posible que un pequeño programa hecho por mí sea capaz de leer y escribir en disco? Bien, la duda es lógica, porque todavía no hemos hablado de las “llamadas o peticiones al sistema” (“syscalls”). |
Las syscalls o llamadas al sistema son:
- El mecanismo por el cual los procesos y aplicaciones de usuario acceden a los servicios del núcleo.
- Son la interfaz que proporciona el núcleo para realizar desde el modo usuario las cosas que son propias del modo kernel (como acceder a disco o utilizar una tarjeta de sonido).
Figura 1.1.1. Mecanismo de petición de servicios al kernel.
Explicación:
- El proceso de usuario necesita acceder al disco para leer, para ello utiliza la syscall read() utilizando la interfaz de llamadas al sistema.
- El núcleo atiende la petición accediendo al hardware y devolviendo el resultado al proceso que inició la petición.
Este procedimiento me recuerda al comedor de un restaurante, en él todos los clientes piden al camarero lo que desean, pero nunca entran en la cocina. El camarero, después de pasar por la cocina, traerá el plato que cada cliente haya pedido. Ningún comensal podría estropear la cocina, puesto que no tiene acceso a ella.
1.2.1. Estructuras de datos
Si queremos implementar la ejecución de varias tareas al mismo tiempo, los cambios de contexto entre tareas y todo lo concerniente a la multiprogramación, es necesario disponer de un modelo de procesos y las estructuras de datos relacionadas para ello.
Un modelo de procesos típico consta de los siguientes elementos:
- PCB (Process Control Block): un bloque o estructura de datos que contiene la información necesaria de cada proceso. Permite almacenar el contexto de cada uno de los procesos con el objeto de ser reanudado posteriormente. Suele ser un conjunto de identificadores de proceso, tablas de manejo de memoria, estado de los registros del procesador, apuntadores de pila, etc.
- Tabla de Procesos: la tabla que contiene todos los PCBs o bloques de control de proceso. Se actualiza a medida que se van creando y eliminando procesos o se producen transiciones entre los estados de los mismos.
- Estados y Transiciones de los Procesos: los procesos se ordenan en función de su información de Planificación, es decir, en función de su estado. Así pues, habrá procesos bloqueados en espera de un recurso, listos para la ejecución, en ejecución, terminando, etc.
- Vector de Interrupciones: contiene un conjunto de apuntadores a rutinas que se encargarán de atender cada una de las interrupciones que puedan producirse en el sistema.
En Linux esto está implementado a través de una estructura de datos denominada task_struct. Es el PCB de Linux, en ella se almacena toda la información relacionada con un proceso: identificadores de proceso, tablas de manejo de memoria, estado de los registros del procesador, apuntadores de pila, etc.
La Tabla de Procesos no es más que un array de task_struct,
extern struct task_struct *pidhash[PIDHASH_SZ];
PIDHASH_SZ determina el número de tareas capaces de ser gestionadas por esa tabla (definida en “/usr/src/linux/include/linux/sched.h”). Por defecto PIDHASH_SZ vale 512, es decir, es posible gestionar 512 tareas concurrentemente desde un único proceso inicial o “init”. Podremos tener tantos procesos “init” o iniciales como CPUs tenga nuestro sistema:
extern struct task_struct *init_tasks[NR_CPUS];
NR_CPUS determina el número de procesadores disponibles en el sistema (definida en “/usr/src/linux/include/linux/sched.h”). Por defecto NR_CPUS vale.1, pero si se habilita el soporte para multiprocesador, SMP, este número puede crecer hasta 32.
1.2.2. Estados de los procesos en linux
En Linux el estado de cada proceso se almacena dentro de un campo de la estructura task_struct. Dicho campo, “state”, irá variando en función del estado de ejecución en el que se encuentre el proceso, pudiendo tomar los siguientes valores:
- TASK_RUNNING (0): Indica que el proceso en cuestión se está ejecutando o listo para ejecutarse. En este segundo caso, el proceso dispone de todos los recursos necesarios excepto el procesador.
TASK_INTERRUPTIBLE (1): el proceso está suspendido a la espera de alguna señal para pasar a listo para ejecutarse. Generalmente se debe a que el proceso está esperando a que otro proceso del sistema le preste algún servicio solicitado.
TASK_UNINTERRUPTIBLE (2): el proceso está bloqueado esperando a que se le conceda algún recurso hardware que ha solicitado (cuando una señal no es capaz de “despertarlo”).
TASK_ZOMBIE (4): el proceso ha finalizado pero aún no se ha eliminado todo rastro del mismo del sistema. Esto es habitualmente causado porque el proceso padre todavía lo espera con una wait().
TASK_STOPPED (8): el proceso ha sido detenido por una señal o bien mediante el uso de ptrace() para ser trazado.
En función del estado de la tarea o proceso, estará en una u otra cola de procesos:
- Cola de Ejecución o runqueue: procesos en estado TASK_RUNNING.
- Colas de Espera o wait queues: procesos en estado TASK_INTERRUPTIBLE ó TASK_ININTERRUPTIBLE.
- Los procesos en estado TASK_ZOMBIE ó TASK_STOPPED no necesitan colas para ser gestionados.
1.2.3. Identificativos de proceso
Todos los procesos del sistema tienen un identificativo único que se conoce como Identificativo de Proceso o PID. El PID de cada proceso es como su CURP
El comando “ps”, que nos informa del estado de los procesos:
pepeton@localhost:~$ ps xa
PID TTY STAT TIME COMMAND
1 ? Ss 0:00 /sbin/init
2 ? S 0:00 [kthreadd]
3 ? S 0:00 [migration/0]
4 ? S 0:00 [ksoftirqd/0]
5 ? S 0:00 [watchdog/0]
6 ? S 0:00 [migration/1]
.
5022 pts/0 S+ 0:00 gnome-pty-helper
5023 pts/1 Ss+ 0:00 /bin/bash
5148 pts/2 Ss 0:00 bash
5165 pts/2 S 0:00 /bin/bash
5182 pts/2 R+ 0:00 ps xa
En la primera columna vemos cómo cada uno de los procesos, incluido el propio “ps xa” tienen un identificativo único o PID. Además de esto, es posible saber quién ha sido el proceso padre u originario de cada proceso, consultando su PPID, es decir, el Parent Process ID.
Además de esto, es posible saber quién ha sido el proceso padre u originario de cada proceso, consultando su PPID, es decir, el Parent Process ID. De esta manera es bastante sencillo hacernos una idea de cuál ha sido el árbol de creación de los procesos, que podemos obtener con el comando “pstree”:
pepeton@localhost:~$ pstree
init─┬─NetworkManager
├─acpid
├─apache2───6*[apache2]
├─atd
├─avahi-daemon───avahi-daemon
├─gnome-settings-
├─gnome-terminal─┬─bash───bash───pstree
│ ├─gnome-pty-helpe
│ └─{gnome-terminal}
├─firefox-bin─┬─plugin-containe───4*[{plugin-contain}]
│ └─25*[{firefox-bin}]
El comando “pstree” es el proceso hijo de un intérprete de comandos (bash) que a su vez es hijo de una sesión de SSH (Secure Shell). Otro dato de interés al ejecutar este comando se da en el hecho de que el proceso init es el proceso padre de todos los demás procesos. Esto ocurre siempre: primero se crea el proceso init, y todos los procesos siguientes se crean a partir de él.
Además de estos dos identificativos existen lo que se conocen como “credenciales del proceso”, que informan acerca del usuario y grupo que lo ha lanzado. Esto se utiliza para decidir si un determinado proceso puede acceder a un recurso del sistema, es decir, si sus credenciales son suficientes para los permisos del recurso. Existen varios identificativos utilizados como credenciales, todos ellos almacenados en la estructura task_struct:
/* process credentials */ uid_t uid,euid,suid,fsuid; gid_t gid,egid,sgid,fsgid;
Su significado es el siguiente :
Identificativos reales | uid | Identificativo de usuario real asociado al proceso | gid | Identificativo de grupo real asociado al proceso |
Identificativos efectivos | euid | Identificativo de usuario efectivo asociado al proceso | egid | Identificativo de grupo efectivo asociado al proceso |
Identificativos guardados | suid | Identificativo de usuario guardado asociado al proceso | sgid | Identificativo de grupo guardado asociado al proceso |
Identificativos de acceso a ficheros | fsuid | Identificativo de usuario asociado al proceso para los controles de acceso a ficheros | fsgid | Identificativo de grupo asociado al proceso para los controles de acceso a ficheros |
Tabla 1.2.1 Credenciales de un proceso y sus significados.
- Obtener enlace
- X
- Correo electrónico
- Otras aplicaciones
Comentarios
Publicar un comentario