Introducción a POSIX (Portable Operating System Interface + UniX) (página 2)
Enviado por Pablo Turmero
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 |