Introducción a POSIX (Portable Operating System Interface + UniX) (página 2)
Ejemplo con fork()
#include
int main(void) {
pid_t id;
id = fork();
if (id == -1) {
perror (“Error en el fork”);
exit (1);
}
if (id == 0) {
while (1) printf (“Hola: soy el hijon”);
} else {
while (1) printf (“Hola: soy el padren”);
}
} /* Fin de main */
Ejecución de programas: exec()
La familia de llamadas exec() se emplea para cargar la imagen de un proceso desde un archivo a memoria
La nueva imagen se carga encima de la del proceso que invoca la llamada, machacándolo
El nuevo proceso hereda:
El PID y el PPID del proceso original
La política de planificación
Las alarmas y señales pendientes
Prototipos de la familia exec()
Definidos en:
#include
int execl (const char *path,
const char *arg, …);
int execlp (const char *file,
const char *arg, …);
int execle (const char *path, const char *arg,
…, char * const envp[]);
int execv (const char *path, char const *argv[]);
int execvp (const char *file, char const *argv[]);
Valores de retorno:
En caso de error exec() devuelve -1
Ejemplo con exec()
#include
int main(void) {
int ret;
char *arg[3];
arg[0] = “ls”;
arg[1] = “-l”;
arg[2] = (char *)0;
printf (“Allá va!n”);
ret = execv (“/bin/ls”, arg);
if (ret == -1) {
perror (“Error en el exec”);
exit (1);
}
} /* Fin de main */
Finalización de procesos: exit()
La llamada exit() provoca la finalización del proceso que la invoca
Esta llamada nunca retorna
Cuando un proceso termina, sus hijos no mueren y suelen ser adoptados por el proceso init
Prototipo definido en:
#include
void _exit (int status);
El valor status es retornado al padre si es que existe
Espera por procesos: wait()
La llamada wait() permite que un proceso quede esperando a que sus hijos terminen
El padre puede conocer el valor de retorno de cada hijo
Prototipos definido en:
#include
#include
pid_t wait (int *status);
pid_t waitpid(pid_t pid, int *status, int
options);
Ejemplo con wait()
#include
#include
int main(void)
{
pid_t id;
int estado;
id = fork();
if (id == -1) {
perror (“Error en el fork”);
exit (1);
}
Continuación del ejemplo
if (id == 0) {
printf (“Soy el hijon”);
sleep(3);
printf (“Hijo: despierta y finalizan”);
exit(0);
} else {
printf (“Soy el padre y ahora espero …n”);
wait (&estado);
printf (“Padre: el hijo terminó con estado =
%dn”, estado);
exit (0);
}
} /* Fin de main */
Planificación
Los mecanismos clásicos de planificación no son válidos
Es necesario evitar el indeterminismo
POSIX 1b utiliza una planificación expulsora con prioridades fijas (32 como mínimo) con tres políticas diferentes:
SCHED_FIFO
FIFO para tareas de igual prioridad
SCHED_RR
Round-Robin en tareas con la misma prioridad. El quanto es fijo
SCHED_OTHER
Definido por la realización concreta
Planificación (continuación)
Los parámetros de planificación y los prototipos de las funciones se encuentran en:
#include
Parámetros de planificación:
struct sched_param {
int sched_priority;
}
Definir política y parámetros (hay que ser root):
int sched_setscheduler (pid_t pid,int policy,
const struct sched_param *param);
Planificación (continuación)
Leer la política y los parámetros:
int sched_getscheduler (pid_t pid);
int sched_getparam (pid_t pid,
struct sched_param *param);
Ceder el procesador:
int sched_yield (void);
Leer los límites de los parámetros:
int sched_get_priority_max (int policy);
int sched_get_priority_min (int policy);
int sched_rr_get_interval (pid_t pid,
struct timespec *interval);
Ejemplo
#include
#include
int main(void) {
pid_t pid;
struct sched_param parametros;
int i, max_prio;
pid = getpid();
max_prio = sched_get_priority_max(SCHED_FIFO);
parametros.sched_priority = max_prio;
sched_setscheduler(pid, SCHED_FIFO, ¶metros);
for (i=0; i<100000000; i++);
} /* Fin de main */
Introducción
La memoria virtual introduce NO determinismo
POSIX proporciona la posibilidad de bloquear memoria para evitar la aleatoriedad
Los procesos a pesar de tener un espacio de direccionamiento disjunto pueden compartir objetos de memoria
La compartición se realiza mapeando la zona de memoria que deseamos compartir en los espacios de direccionamiento virtuales de cada proceso
La compartición se realiza a través de páginas de modo que el tamaño de una zona proyectada es un múltiplo del tamaño de la página
Bloqueo de memoria
Los procesos pueden bloquear todas sus páginas en memoria para evitar el intercambio con el disco
#include
int mlockall (int flags);
El valor de flags puede ser:
MCL_CURRENT: afecta a las páginas actuales
MCL_FUTURE: afecta a las páginas futuras
Para liberar todas las páginas del proceso:
int munlockall (void);
Bloqueo de memoria
Un proceso pueden bloquear también un rango de su espacio de direccionamiento
int mlock (const void *addr, size_t len);
Para desbloquear un rango de direcciones:
int munlock (const void *addr, size_t len);
Memoria compartida
M. Compartida
M. Compartida
M. Compartida
Proceso 1
Proceso 2
Memoria física
Proyección de objetos en memoria
La llamada mmap() permite proyectar objetos en memoria
Estos objetos pueden ser compartidos
Función mmap():
void *mmap (void *addr, size_t len, int prot,
int flags, int fildes, off_t off);
El objeto queda identificado por fildes
len y off son la longitud y el offset del objeto en bytes respectivamente
addr es la dirección donde deseamos proyectar el objeto preferiblemente. Es sólo una indicación
Proyección de objetos en memoria
La dirección real donde se proyecta el objeto es devuelta por mmap()y depende del valor de flags:
MAP_FIXED: addr se interpreta de forma exacta, sin este flag si addr vale NULL, el sistema elige la dirección
MAP_SHARED: los cambios son compartidos
MAP_PRIVATE: no se comparten los cambios
prot especifica el tipo de acceso:
PROT_READ: derecho de lectura
PROT_WRITE: derecho de escritura
PROT_EXEC: derecho de ejecución
PROT_NONE: sin derechos
Proyección de objetos en memoria
Para eliminar la proyección de un objeto en memoria emplearemos la función munmap()
int munmap (void *addr, size_t len);
Objetos de memoria compartida
Para abrir un objeto de memoria compartida:
#include
int shm_open (const char *path, int oflag,
mode_t mode );
Se establece una conexión entre el path que identifica al objeto y el descriptor devuelto
oflag determina el modo de acceso
mode determina los derechos de acceso si creamos un nuevo objeto
Es recomendable por razones de portabilidad que el path comience con el carácter /
Objetos de memoria compartida
Fijar el tamaño de un objeto de memoria compartida
int ftruncate (int fildes, off_t length);
Para borrar un objeto de memoria compartida:
int shm_unlink (const char *path);
Página anterior | Volver al principio del trabajo | Página siguiente |