Identificador de Procesos
Cada proceso tiene un identificador único (PID).
Este es un entero no negativo asignado por el sistema. Puede ser usado
para garantizar unicidad dentro de una máquina.
Aplicación: este valor es usado por las funciones:Algunos procesos importantes:
#include <stdio.h>
char *tmpnam(char *ptr);
la cual retorna un pathname único.
y
FILE *tmpfile(void);
Este archivo es automaticamente borrado or removido cuando es cerrado.
Scheduler -> Identificador 0Funciones para obtener el identificador de un prceso:
/sbin/init -> Identificador de proceso 1
Otras funciones relacionadas con otros identificadores en el sistema UNIX:
uid_t getuid(void);
retorna el identificador de usuario real.
uid_t geteuid(void);
retorna el identificador de usuario efectivo.
gid_t getgid(void);
retorna el identificador de grupo real
gid_t getegid(void);
retorna el identificador de grupo efectivo.
Función fork
Esta es la "única" manera de
crear un nuevo proceso en UNIX. (excepciones PID 0, PID 1)
Uso:La función es llamada una vez, por el proceso padre, pero retorna dos veces.
#include <sys/types.h>
#include <unistd.h>pid_t fork(void);
Retorna: 0 en hijo y el identificador de hijo en el padre. -1 es retornado en caso de error.
Ejemplo de uso de la función fork.
Ejercicios: Cual es la salida de
a) % a.out
b) % a.out > temp.out
% cat temp.out
Efecto en archivos: todos los descriptodes de archivo son "duplicados". Padre e hijo comparten la tabla de entrada de archivos de cada descriptor abierto. Es decir, ambos ven el mismo puntero de escritura y lectura.
EL conjunto de alarmas pendientes en le padre no son pasadas al hijo. El hijo parte sin alarmas pendientes. Los locks del padre tampoco son pasados.
Funciones de terminación
Hay 5 formas en que un proceso puede
terminar:
Terminación normal:
#include <stdlib.h>
void exit( int status);
#include <unistd.h>
void _exit(init status);
#include <stdlib.h>
int atexit(void (*func) (void)); // retorna 0 si
es OK, distinto de 0 en otro caso.
Terminación anormal:
Llamar a abort: esta función
genera la señal SIGABRT, por lo tanto es un caso particular del
siguente caso.
Las señales pueden ser generadas
por el mismo proceso, otro, o el kernel. Ejemplos: cuando referencias a
memoria fuera de su espacio, división por cero, control-C, etc.
Cuando un proceso termina su estatus de termino (exit
status) es pasado al proceso padre.
Qué pasa si el padre termina primero?
El proceso init se hace cargo de todos los hijos cuyos padres han terminado.
Qué pasa si el hijo termina primero?
El proceso padre debe esperar por su estatus de término.
El kernel mantiene esta información hasta que el padre la solicita.
Si no lo hace el proceso se convierte en un proceso "zombie".
Funciones wait y waitpid
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait (int *statloc);
pid_t waitpid( pid_t pid, int *statloc, int options);
Cómo podemos crear un hijo,
sin esperar por su codigo de retorno y sin crear un proceso Zombie?
Respuesta
Función exec
Es usada para
ejecutar otro programa luego de haber creado un proceso hijo.
Hay 6 formas
de la función exec.
Cuando una de
ellas es llamada, el proceso completo es reemplazado por un nuevo programa.
El nuevo programa
parte en su función main.
El nuevo progama
no cambia el identificador de proceso.
#include <unistd.h>
int execl (const
char *pathname, const char *arg0, ... , (char *) 0);
int execv (const
char *pathname, char * const argv[]);
int execle (const
char *pathname, const char *arg0, ... , (char *) 0, char * const envp[]);
int execve (const
char *pathname, char * const argv[], char * const envp[]);
int execlp (const
char *filename, const char *arg0, ... , (char *) 0);
int execvp (const
char *filename, char * const argv[]);
Valor retornado: -1 en caso de error, Qué retorna en caso de éxito?
Función system
#include <stdlib.h>
int system (const
char * cmdstring);
Esta función es internamente implementada llamando a las funciones fork, exec, y waitpid.
Ejemplo de uso: para almacenar el
tiempo y fecha en que parte del código fue ejecutado,
:
system("date
> file");
: