Documentos de Académico
Documentos de Profesional
Documentos de Cultura
_Gua de Trabajo No 6_
Objetivo_
_Estudiar los conceptos bsicos de los servicios POSIX para la gestin de procesos
empleada por los Sistemas Operativos GNU/Linux
Indicaciones_ Habiendo ledo sus apuntes, material visto en clases y la lectura de Servicios
POSIX para la gestin de procesos, resuelva o plantee una solucin a una serie de
interrogantes y problemas que a continuacin se le presentan, donde se destacan los puntos
bsicos de la gestin de procesos en el Sistema Operativo GNU/Linux.
Material de Apoyo_
_Definicin de Proceso
Un programa es una secuencia de instrucciones escrita en un lenguaje de programacin. Un
proceso es una instancia de ejecucin de un programa. Un programa es un concepto esttico,
mientras que un proceso es un concepto dinmico. En un entorno multiusuario, es posible que
varios usuarios ejecuten el mismo programa, obteniendo un proceso distinto por cada
ejecucin.
_Estados de un Proceso en el Kernel Linux
En un entorno multitarea coexisten varios procesos que se ejecutan de manera entrelazada (un
nico procesador). Sin embargo, algunos procesos se encuentran esperando eventos, por
ejemplo esperando a que el usuario pulse una tecla, dicha espera se debe realizar de manera
que se perjudique lo menos posible al resto de procesos, con los que se comparte la CPU.
Si se realiza espera activa, cada vez que el sistema operativo le asigne la CPU a dicho
proceso, ste mirar el teclado a ver si se ha pulsado una tecla, y esto lo repetir hasta
que dicho evento se produzca. Durante todo ese tiempo, el proceso est consumiendo
innecesariamente CPU. Para evitar la espera activa, los procesos se suspenden a espera de
eventos, de manera que dichos procesos no entren en el reparto de la CPU. A continuacin se
enumeran los distintos estados en los que se puede encontrar un proceso:
_Preparados (R): Conjunto de procesos que pueden ejecutarse en este momento, es decir,
disponen de todos los recursos necesarios para poder ejecutarse, salvo la CPU. El
sistema operativo les ir asignando la CPU a cada uno de ellos.
_Ejecutando (O): El proceso ocupa actualmente la CPU: Slo uno de los procesos
preparados se estar ejecutando en cada momento (monoprocesador).
_Suspendidos (S): A dichos procesos les falta, adems de la CPU, algn recurso para
poder ejecutarse, entendindose por recurso un dispositivo, un dato, etc. Los procesos
suspendidos estn esperando a que ocurra algn evento para poder acceder al recurso
que necesitan. Estos procesos no entran en el reparto de la CPU, evitando as la
espera activa. Cuando se produce el evento esperado, dicho proceso pasar a estar
preparado.
_Sistemas Operativos_
_24-09-2015_
_Parados (T): Son procesos que tampoco entran en el reparto de la CPU, pero que no
estn suspendidos a la espera de eventos, sino que han sido parados en su ejecucin.
Para salir de dicho estado hay que mandarles continuar, volviendo as a estar
preparados.
_Zombies (Z): Cuando un proceso finaliza, se lo comunica a su proceso padre (el
proceso que lo cre). Si dicho proceso no captura el aviso de su proceso hijo, ste
queda en un estado zombies. En dicho estado, el proceso no consume CPU pero sigue
ocupando recursos en la tabla de procesos (donde se guarda informacin de cada uno de
los procesos existentes en el sistema). Un proceso permanece zombi hasta que su
proceso padre captura su aviso.
_Identificacin de Procesos
Cada proceso se identifica mediante su PID (identificador de proceso), que es un nmero
entero (mayor que cero) que el sistema va asignando a cada proceso cuando ste se crea.
El sistema operativo Unix y Linux proporciona un comando que nos da informacin relativa a
cada uno de los procesos que existen en el sistema. Para obtener todos los procesos
correspondientes a un usuario
usuario: ps -aux | grep usuario. Se recomienda ver el manual (man ps).
USER: El propietario del proceso.
PID: El identificador del proceso.
%CPU: Porcentaje de CPU consumida.
%MEM: Porcentaje de memoria consumida.
SIZE: Tamao total del proceso (Kb).
RSS: Kilobytes del programa en memoria. (El resto estar en disco (swap)).
TTY: Identificador del terminal desde donde se lanz el proceso.
STAT: Estado del proceso.
START: Hora en la que empez o la que se lanz el proceso.
TIME: Tiempo de CPU consumido.
COMMAND: Nombre del proceso.
Otros comandos interesantes:
top, htop
_Sistemas Operativos_
_24-09-2015_
_Sistemas Operativos_
_24-09-2015_
La siguiente figura muestra que la clonacin del proceso padre se realiza copiando la imagen
de memoria y el BCP. Observe que el proceso hijo es una copia del proceso padre en el
instante en que ste solicita el servicio fork. Esto significa que los datos y la pila del
proceso hijo son los que tiene el padre en ese instante de ejecucin. Es ms, dado que, al
entrar
el
sistema
operativo a tratar el
servicio, lo primero
que hace es salvar los
registros en el BCP
del padre, al copiarse
el BCP se copian los
valores salvados de
los registros, por lo
que el hijo tiene los
mismos valores que el
padre.
_Sistemas Operativos_
_24-09-2015_
Esto significa, en especial, que el contador de programa de los dos procesos tiene el mismo
valor, por lo que van a ejecutar la misma instruccin mquina. No hay que caer en el error
de pensar que el proceso hijo empieza la ejecucin del cdigo en su punto de inicio.
Repetimos que el hijo empieza a ejecutar, al igual que el padre, en la sentencia que est
despus del fork.
En realidad, el proceso hijo no es totalmente idntico al padre, puesto que algunos de los
valores del BCP han de ser distintos. Las diferencias ms importantes son las siguientes:
_El proceso hijo tiene su propio identificador de proceso, distinto al del padre.
_El proceso hijo tiene una nueva descripcin de la memoria. Aunque el hijo tenga los
mismos segmentos con el mismo contenido, no tienen por qu estar en la misma zona de
memoria (esto es especialmente cierto en el caso de sistemas sin memoria virtual).
_El tiempo de ejecucin del proceso hijo se iguala a cero.
_Todas las alarmas pendientes se desactivan en el proceso hijo.
_El conjunto de seales pendientes se pone a vaco.
_El valor que retorna el sistema operativo como resultado del fork es distinto en el
hijo y el padre.
Ejemplo:
En el ejemplo que se muestra a continuacin, se crea un proceso hijo que imprime en pantalla
el PID de su proceso padre, mientras que el proceso padre imprime en pantalla su propio PID
y el del proceso hijo que ha creado. Para ello, se utilizan servicio getpid() y getppid().
El proceso padre, antes de finalizar se suspende hasta que el hijo muere, para evitar que
ste se quede zombi. Para ello, utiliza servicio wait() [consulte el manual del programador
de linux para mayor informacin del servicio wait ($ man 2 wait)], que recibe en la variable
status el estado de que el proceso hijo finaliz.
/*
* File:
main.c
* Author: logan
*
* Created on 20 de septiembre de 2015, 08:41 PM
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
pid_t pid;
int status = 0, pid_hijo_terminado = 0;
if ((pid = fork()) == -1) {
printf("Error al crear proceso hijo!!!\n");
exit(1);
}
if (pid == 0) {
/* Proceso Hijo */
printf("El PID de mi proceso padre es %d:\n ", getppid());
exit(1);
} else {
/* Proceso Padre */
printf("Mi PID es el %d y he creado un proceso hijo y su pid es %d\n", getpid(), pid);
pid_hijo_terminado = wait(&status);
printf("\nEl proceso hijo [pid] = %d, finalizo con el estado %d\n", pid_hijo_terminado, status);
}
return (0);
}
_Ejecucin de un Programa
El servicio exec de POSIX tiene por objetivo cambiar el programa que est ejecutando un
proceso. Se puede considerar que el servicio tiene dos fases. En la primera se vaca el
proceso de casi todo su contenido, mientras que en la segunda se carga en nuevo programa. La
siguiente figura muestra estas dos fases.
_Sistemas Operativos_
_24-09-2015_
SINOPSIS
#include <unistd.h>
extern char **environ;
int
int
int
int
int
DESCRIPCIN
La familia de funciones exec reemplaza la imagen del proceso en curso con una nueva.
Las funciones descritas en esta pgina del Manual son interfaces para la primitiva
execve(2). (Consulte la pgina del Manual de execve para informacin detallada acerca
del reemplazo del proceso en curso.)
_Sistemas Operativos_
_24-09-2015_
Si la llamada se ejecuta con xito, sta no devolver ningn valor puesto que la imagen del
proceso habr sido reemplazada, en caso contrario devuelve -1.
La funcin main del nuevo programa llamado tendr la forma:
int main(int argc, char **argv)
donde argc representa el nmero de argumentos que se pasan al programa, incluido el propio
nombre del programa, y argv es un vector de cadenas de caracteres, conteniendo cada elemento
de este vector un argumento pasado al programa. El primer componente de este vector (argv
[0]) representa el nombre del programa.
El argumento path apunta al nombre del archivo ejecutable donde reside la nueva imagen del
proceso. El argumento file se utiliza para construir el nombre del archivo ejecutable. Si el
argumento file contiene el carcter /, entonces el argumento file constituye el nombre del
archivo ejecutable. En caso contrario, el prefijo del nombre para el archivo se construye
por medio de la bsqueda en los directorios pasados en la variable de entorno PATH.
El argumento argv contiene los argumentos pasados al programa y debera acabar con un
puntero NULL. El argumento envp apunta al entorno que se pasar al nuevo proceso y se
obtiene de la variable externa environ.
Ejemplo: A continuacin se muestra un ejemplo de utilizacin de la llamada execlp. Este
programa crea un proceso hijo, que ejecuta el comando ls -l, para listar el contenido del
directorio actual de trabajo.
/*
* File:
fexecvp.c
* Author: logan
*
* Created on 23 de septiembre de 2015, 06:37 PM
*/
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<unistd.h>
<sys/types.h>
int main() {
pid_t pid;
pid = fork();
switch(pid) {
case -1:
exit(-1);
case 0:
execlp("ls", "ls", "-l", NULL);
perror("exec");
break;
default:
printf("Proceso Padre\n");
}
return (EXIT_SUCCESS);
_Terminacin de Procesos
Un proceso puede terminar su ejecucin de forma normal o anormal. Un proceso puede terminar
su ejecucin de forma normal usando cualquiera de las tres formas siguientes:
_Ejecutando una sentencia return en la funcin main.
_Ejecutando la llamada exit.
_Ejecutando la llamada _exit.
Cuando un programa ejecuta dentro de la funcin main la sentencia return(valor), sta es
similar a exit(valor). El prototipo de la funcin exit es:
void exit(int status);
_Sistemas Operativos_
_24-09-2015_
Estos servicios tienen por funcin finalizar la ejecucin de un proceso. Ambos reciben como
parmetro un valor que sirve para que el proceso d una indicacin de cmo ha terminado.
La finalizacin de un proceso tiene las siguientes consecuencias:
_Se cierran todos los descriptores de archivos.
_La terminacin del proceso no finaliza de forma directa la ejecucin de sus procesos
hijos.
_Si el proceso padre del proceso que realiza la llamada se encuentra ejecutando una
llamada wait o waitpid, se notifica la terminacin del proceso.
_Si el proceso padre no se encuentra ejecutando una llamada wait o waitpid, el cdigo
de finalizacin (status) se salva hasta que el proceso padre ejecute la llamada wait o
waitpid.
_El sistema operativo libera todos los recursos utilizados por el proceso.
Un proceso tambin puede terminar su ejecucin de forma anormal, llamando a la funcin
abort, por la recepcin de una seal que provoca su finalizacin. La seal puede ser causada
por un evento externo (ej: se pulsa CTRL-C), por una seal enviada por otro proceso, o por
un error de ejecucin, como, por ejemplo, la ejecucin de una instruccin ilegal, un acceso
ilegal a una posicin de memoria, etc.
En realidad, exit es una funcin de biblioteca que llama al servicio _exit despus de
preparar la terminacin ordenada del proceso.
Para tener un mejor panorama y explicacin de las funciones de biblioteca aqu planteadas
puede consultar el manual del sistema [man] en las secciones 2 y 3.
MAN(1)
MAN(1)
NOMBRE
SINOPSIS
man [-c|-w|-tZT dispositivo] [-adhu7V] [-m sistema[,...]] [-L locale] [-p cadena] [-M
ruta] [-P paginador] [-r prompt] [-S lista] [-e extension]
[[seccin] pagina ...] ...
man -l [-7] [-tZT dispositivo] [-p cadena] [-P paginador] [-r prompt] fichero ...
man -k [-M ruta] palabra_clave ...
man -f [-M ruta] pagina ...
DESCRIPCIN
man es el paginador del manual del sistema. Las pginas usadas como argumentos al ejecutar man
suelen ser normalmente nombres de programas,
tiles
o funciones. La
pgina
de
manual
associada con cada uno de esos argumentos es buscada y presentada. Si la llamada da tambin la
seccin, man buscar slo en dicha seccin del manual. Normalmente, la bsqueda se lleva a cabo
en todas las secciones de manual
disponibles
segn
un
orden predeterminado, y slo se
presenta la primera pgina encontrada, incluso si esa pgina se encuentra en varias secciones.
La siguiente tabla muestra los nmeros de seccin del manual y los tipos de pginas que
contienen.
1
2
3
4
5
6
7
8
9
n
l
p
o
_Sistemas Operativos_
_24-09-2015_
_24-09-2015_
<stdio.h>
<unistd.h>
<string.h>
<stdlib.h>
_Sistemas Operativos_
_24-09-2015_
/*
* File:
p2.c
* Author: logan
*
* Created on 23 de septiembre de 2015, 07:54 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv) {
int i;
char a[2000000];
printf("Ejecutando el programa invocado.- (p2).- Sus argumentos son: \n");
for (i = 0; i < argc; i++)
printf("argv[%d]: %s\n", i, argv[i]);
sleep(10);
return (EXIT_SUCCESS);
-------------------------------------------------------------------------------------------------
$ ps -l
Nota: Para observar cunta memoria ocupa cada programa, realice un ps l una vez el
proceso ha escrito en pantalla el mensaje correspondiente (hay 10 segundos de plazo antes de
realizar el execv en
p1 y antes de terminar en p2).
Responda a las siguientes preguntas:
_Escriba el contenido de los elementos del vector argv que recibe p1 y los que recibe
p2.
_Qu PID tiene el proceso que ejecuta p1.c? Y el de p2.c?
_Qu tamao de memoria utiliza el proceso, segn se ejecuta p1 o p2?
-------------------------------------------------------------------------------------------------
_Sistemas Operativos_
_24-09-2015_
/*
* File:
pfork2.c
* Author: logan
*
* Created on 20 de septiembre de 2015, 08:12 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int i, j;
pid_t pid;
pid = fork();
switch (pid) {
case -1:
printf("\nERROR.- No se ha podido crear el proceso hijo.-");
break;
case 0:
i = 0;
printf("\nSoy el Proceso Hijo, mi PID es %d y mi variable i
(valor inicial: %d) es par", getpid(), i);
for (j = 0; j < 5; j++) {
i++;
i++;
printf("\nSoy el Proceso Hijo, mi variable i es: %d", i);
}
break;
default:
i = 1;
printf("\nSoy el Proceso Padre, mi PID es %d y mi variable i
(valor inicial: %d) es impar", getpid(), i);
for (j = 0; j < 5; j++) {
i++;
i++;
printf("\nSoy el Proceso Padre, mi variable i es: %d", i);
};
}
printf("\nFinal de ejecucion de %d \n", getpid());
return (EXIT_SUCCESS);
}
-------------------------------------------------------------------------------------------------
En el programa anterior, el proceso padre visualiza los sucesivos valores impares que toma
su variable i privada, mientras el proceso hijo visualiza los sucesivos valores pares que
toma su variable i privada y diferente a la del proceso padre.
Compile el el programa, haciendo uso del comando gcc.
Responda a las siguientes preguntas:
_Las variables enteras i y j del proceso padre son las mismas que las del proceso
hijo?
_Qu cambios deberan realizarse en el cdigo para que ambos procesos partieran de
igual valor de la variable entera i, y adems un proceso realice su cuenta de uno en
uno y el otro proceso de dos en dos? Editar el programa, compilarlo y comprobar su
ejecucin.
_Sistemas Operativos_
_24-09-2015_
int main() {
pid_t pid;
pid = fork();
switch (pid) {
case -1:
printf("\nERROR.- No se ha podido crear el proceso hijo.-");
break;
case 0:
printf("\nSoy el Proceso Hijo, mi PID es %d y mi PPID es %d\n", getpid(), getppid());
sleep(10);
break;
default:
printf("\nSoy el Proceso Padre, mi PID es %d y el PID de mi Hijo es: %d\n", getpid(), pid);
wait(0);
}
printf("\nFinal de ejecucion de %d \n", getpid());
return (EXIT_SUCCESS);
------------------------------------------------------------------------------------------------_Sistemas Operativos_
_24-09-2015_
/*
* File:
jfork1.c
* Author: logan
*
* Created on 23 de septiembre de 2015, 10:24 AM
*/
#include
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<unistd.h>
<sys/types.h>
<sys/wait.h>
_Sistemas Operativos_
_24-09-2015_
Profundidad 5
Anchura 3
_Sistemas Operativos_
_24-09-2015_