Bueno, estoy de exámenes y aunque he seguido pasandome por estos lugares no quería postea ni liarme en nada porqué ya pierdo bastante el tiempo yo solo.
El caso es que me comprometí a dar una charla sobre procesos en el IRC, y como he estado desaparecido no ha podido ser. El caso es que tenía la conciencia intranquila, y ahora en un arrebato he escrito esto. Lo he hecho muy a lo loco y sin pensar, así que me disculpo por adelantado ya que he dejado demasiadas cosas en el tintero, y probablemente me haya expresado bastante mal fruto de la prisa...
En cualquier caso lo de la charla sigue en pie, así que espero que esto sirva como tentenpié para ésta. Desde luego que me tomaré algo más de tiempo para escribir la próxima vez, e intenaré profundizar un poco más (aunque no demasiado que sino se me irá la cosa de las manos).
¿Que es un proceso?No hay que confundir la palabra programa con proceso. Cuando se habla de "
programa" se hace referencia al código escrito en cierto lenguaje de programación, mientras que cuando hablamos de "
proceso", nos referimos a una instancia de ejecución de un programa (contador, palabra de estado, registros, pila, etc).
Se suele decir que un programa es un concepto estático, y proceso un concepto dinámico.
PCB y tabla de procesosLa CPU solo puede hacer un trabajo, de modo que aún que hayan varios procesos ejecutados, en un momento dado solo uno estará realmente en ejecución.
El sistema operativo será el encargado de repartir el trabajo a la CPU, para ello existe una
tabla de procesos con un
PCB (Bloque de Control de Proceso) para cada proceso en ejecución. Este bloque es una estructura de datos con toda la información relativa a un proceso:
- Identificador
- Estado (ejecución, preparado, bloqueado)
- Prioridad
- Padres e hijos
- Punteros a zonas de memoria (pila, datos, etc)
- PC, PSW, registros
- TDF
- etc.
El
PID, es el número único que identificará al proceso.
En cuánto a los estados, como hemos dicho, la CPU sólo puede realizar una tarea a la vez de modo que mientras un proceso está en la CPU diremos que esta en
"ejecución". Los procesos "preparados" son los que estan a la espera de que se les asigne la CPU (cola de procesos preparados). El resto son los procesos
"bloqueados", que no estarán preparados hasta un determinado evento (termina transferencia E/S por DMA, llega una señal, etc). Cabe destacar que todo esto
ocupa espacio en memória, de modo que el número de procesos que puede haber en una máquina puede quedar muy limitado, por eso el sistemao operativo también se encargará de llevar a disco algunos procesos que tardarán en ejecutarse o salir de "bloqueados" y así aumentar la capacidad de procesos simultáneos.
Planificador de procesos (Scheduler) y despachador (Dispatcher)El scheduler viene a ser el jefazo, el encargado de gestionar todo este lío. A priori se distinguen tres niveles:
-
A largo plazo; decide sobre la creación de nuevos procesos, controla el grado de
multiprogramación.
-
Medio plazo; el encargado del
swapping, intercambio de procesos entre memoria y disco.
-
A corto plazo; se invoca cada interrupción, decide que proceso de los preparados pasa a ejecutarse.
El problema que surge ahora es decir basta a un proceso, tenemos una cola de procesos ansiosos por llegar a CPU y si esta ocupada nunca podrán llegar. El
primer paso para solventar esto son los sistemas de multiprogramación, para aumentar el rendimiento de la máquina (a diferencia de sus antecesores los sistemas monoprogramados) no desperdician tiempo de CPU. Si un proceso pide E/S, se pasa a bloqueado hasta que termine la transferencia y así otro puede
pasar a ejecución, en lugar de esperar que termine la E/S, vuelva a ejecución y termine la ejecución. Pero esto no sirve para sistemas de tiempo compartido,
la solució básica es poner un
quantum (cada x msg llega interrupción, llama a scheduler y mueve a preparado el proceso, ejecuta otro). A partir de esto hay muchas implementaciones que tienen en cuenta distintos factores: prioridades, antiguedad, duración, etc.
En cualquier caso el sistema va a ir rotando el proceso que se encuentra en ejecución para que nadie quede marginado, y para ello hay que realizar cambios
de contexto. Tenemos que salvar la información necesária para que el proceso pueda volver a ejecutarse por dónde estaba, así que el dispatcher va a actualizar
nuestro PCB (estado, PC, PSW, registros, etc), y va a restaurar el contexto del proceso que el scheduler manda a ejecución.
Fork()Crea un duplicado del proceso que lo realiza. El nuevo proceso es el hijo, y el creador el padre.
Algoritmo general:
- busca entrada libre en tabla de procesos y un PID único
- copia los datos del padre al PCB del hijo
- modifica algunos campos: tiempo, PID...
- reserva espacio en memoria y duplica zonas del padre
- copia TDF (tabla de descriptores de fichero)
- devuelve el PID del hijo al proceso padre y cero al hijo
- coloca a los dos procesos en estado preparado
- llama a scheduler
(continuará ejecutándose a partir de la llamada fork (PC no cambia))
Ejemplo:Language: C
main() {
int pid;
switch(pid=fork()) {
case -1: exit(1); /* error */
case 0: /* hijo */
printf("hola soy el hijo\n");
default: /* padre */
printf("hola soy el padre\n");
}
exit(0); /* ambos */
}
exec()Sustituye la imagen del proceso que realiza la llamda por la almacenada en un fichero ejecutable. La identidad del proceso no cambia.
Algoritmo general:
- Conseguir imagen del programa a ejecutar (comprobar si es ejecutable, blablabla)
- salva los parametros de exec()
- libera regiones de memoria del proceso
- reserva espacio para las nuevas
- carga contenido del fichero
- modifica campos del PCB (PC, puntero de pila, ...)
- carga parámetros a la pila del proceso
- estado a preparado
- llama scheduler
Ejemplo:Language: C
main() {
execl("/bin/ls","ls","-l",0);
printf("Error\n"); exit(1);
}
Y esto es una demasiado resumida y mala introducción a los procesos en UNIX. De nuevo disculpas y un saludo! ^^
PD: Dudas, discrepancias, valoraciones, etc. Comentarlo, así lo hago mejor la próxima vez.