Clases 04 y 05: Repaso de programación de sistemas basados en UNIX 1 Prof. Edgardo Adrián Franco Martínez http://computacion.cs.cinvestav.mx/~efranco efranco.docencia@gmail.com Estructuras de datos (Prof. Edgardo A. Franco) • Introducción • Scripts • Concepto de proceso • Paso de argumentos • PID, UID y variables de ambiente • Creación de procesos • Tuberías • Hilos Sistemas operativos II Clases 04 y 05: Repaso de programación de sistemas basados en UNIX Contenido Contenido 2 • El sistema operativo UNIX así como sus clones derivados (LINUX, MAC OS, MINIX, etc.), mantienen características comunes en su interfaz POSIX (Portable Operating System Interface la X viene de UNIX). • UNIX es un sistema operativo multiusuario, lo cual significa que dos o mas usuarios pueden trabajar al mismo tiempo y en sesiones distintas sobre un mismo sistema de computo. • También UNIX es un sistema operativo multiproceso, es decir que puede ejecutar dos o más programas de manera simultánea. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Introducción Introducción 3 • El Shell de Unix o también conocido como intérprete de comandos, consiste en la interfaz de usuario tradicional de los sistemas operativos basados en Unix y similares como GNU/Linux. • Mediante las instrucciones que aporta el intérprete, el usuario puede comunicarse con el núcleo y por ende ejecutar dichas órdenes, así como herramientas que permiten controlar el funcionamiento del sistema. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Shell de UNIX Shell de UNIX 4 • Los comandos de UNIX, pueden usarse a modo de guión si se escriben en archivos ejecutables denominados shellscripts, de este modo, cuando se necesita hacer uso de varios comandos o combinación de estos con herramientas, se escribe un script marcado como ejecutable y las operaciones que posteriormente, línea por línea, el intérprete traducirá. • Sin ser un shell estrictamente un lenguaje de programación, el proceso de crear scripts de shell se le conoce como programación shell (shell programming o shell scripting). #!/bin/bash clear ls -a cd home Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Scripts Scripts 5 • Un proceso es un programa en ejecución, los procesos son gestionados por el sistema operativo y están formados por: • Las instrucciones de un programa destinadas a ser ejecutadas por el microprocesador. • Su estado de ejecución en un momento dado, esto es, los valores de los registros de la CPU para dicho programa. • Su memoria de trabajo, es decir, la memoria que ha reservado y sus contenidos. • Otra información que permite al sistema operativo su planificación. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Concepto de proceso Concepto de proceso 6 • Durante la ejecución de un programa (proceso), todos los datos manipulados (incluido el propio código del programa compilado) se alojan en la memoria principal, ya que esta ofrece menor latencia respecto de los medios secundarios. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Concepto de proceso Concepto de proceso 7 • Empezando por la direcciones más bajas, el segmento de código es la porción de la memoria donde se cargará el programa que comenzará a ejecutarse. • El segmento de datos alberga las declaraciones globales (e.g. variables y constantes globales). • El montículo es la región de memoria que se toma y se libera de manera dinámica durante la ejecución del programa. • La pila es donde se "apilan" porciones de memoria pertenecientes a funciones y/o procedimientos cuando se les llama. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Concepto de proceso Concepto de proceso 8 • Los procesos son creados y destruidos por el sistema operativo, así como también este se debe hacer cargo de la comunicación entre procesos, pero lo hace a petición de otros procesos. El mecanismo por el cual un proceso crea otro proceso se denomina bifurcación (fork). Los nuevos procesos pueden ser independientes y no compartir el espacio de memoria con el proceso que los ha creado o ser creados en el mismo espacio de memoria. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Concepto de proceso Concepto de proceso 9 • Un argumento o parámetro es una variable que puede ser recibida por una rutina o subrutina. Una subrutina usa los valores asignados a sus argumentos para alterar su comportamiento en tiempo de ejecución. #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int tokens; for(tokens=0;tokens<argc;tokens++) { if(argv[tokens][0]=='-') printf("opción %s\n",argv[tokens]+1); else(argv[tokens][0]=='-') printf("argumento %d: %s\n",tokens,argv[tokens]); } exit(0); } Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Paso de argumentos Paso de argumentos 10 • Para administrar los procesos, el sistema identifica cada uno mediante su PID. De manera análoga, para administrar a los usuario del sistema, se utiliza un identificador de usuario conocido como UID. #include <sys/types.h> #include <stdio.h> int main(void) { pid_t id_proceso; pid_t id_padre; id_proceso=getpid(); id_padre=getppid(); printf("Identificador del proceso: %d\n",id_proceso); printf("Identificador del proceso padre: %d\n",id_padre); exit(0); } Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX PID, UID y variables de ambiente PID, UID y variables de ambiente 11 • Una variable del entorno es un valor dinámico cargado en la memoria, que puede ser utilizado por varios procesos que funcionan simultáneamente. En la mayoría de los sistemas operativos, la ubicación de algunas bibliotecas o de los archivos ejecutables del sistema más importantes puede variar según la instalación. #include <stdlib.h> #include <stdio.h> extern char **environ; int main(int argc, char *argv[]) { int j; printf("Las variables de entorno para %s son\n",argv[0]); for(j=0;environ[j]!=NULL;j++) printf("environ[%d]=%s\n",j,environ[j]); return 0; } Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX PID, UID y variables de ambiente PID, UID y variables de ambiente 12 • En todo sistema UNIX siempre tendremos un proceso a partir del cual se va generando todo el árbol de procesos. Este proceso padre de todos los procesos se conoce como INIT y su PID es 1. • Cada vez que ejecutamos uno de nuestros programas tenemos un proceso, sin embargo es posible crear uno o más procesos adicionales. (Esto logra tener programas más poderosos, con menos líneas de código y hasta más claro y comprensible). Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Creación de procesos Creación de procesos 13 #include <stdlib.h> #include <stdio.h> #include <sys/types.h> int main() { pid_t pid; int i=0, estado; pid_=fork(); switch(pid) { case -1: //Error printf("Error en el fork"); break; case 0: //Proceso hijo printf("Soy el hijo: PID %d; PPID=%d i=%d\n",getpid(),getppid(),++i); exit(0); break; default: //Proceso padre printf("Soy el padre: PID %d; PPID=%d i=%d\n",getpid(),getppid(),--i); wait(&estado); } } Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Creación de procesos Creación de procesos 14 • Un mecanismo en UNIX para comunicar dos procesos son las tuberías. Una tubería permite conectar un flujo de salida de un proceso a la entrada de otro proceso. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Tuberías Tuberías 15 int main(void) { int bytes_enviados, bytes_leidos, i, descriptor_archivo[2]; char buffer[BUFSIZ+1]; pid_t pid; if(pipe(decriptor_archivo)==0) { pid=fork(); if (pid==-1) { perror("Error al ejecutar el fork"); exit(-1); } if(pid==0) { //Proceso hijo for(i=0;i<27;i++) { memset(buffer,'\0',sizeof(buffer)); bytes_leidos=read(descriptor_archivo[0],buffer,BUFSIZ); printf("El proceso hijo ha leído %d bytes y el contenido es: %s\n",bytes_leidos,buffer); } exit(0); } else { //Proceso padre for(i=65;i<91;i++) { byes_enviados=write(descriptor_archivo[1],(char *)&i, sizeof(char)); printf("El proceso padre ha enviado por la tuberia %d Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Tuberías Tuberías bytes\n",bytes_enviados); sleep(1); } } } exit(0); 16 • En el caso de sistemas operativos multihilo, donde un proceso consta de uno o más hilos, la memoria de trabajo (compartida por todos los hilos) y la información de planificación. Cada hilo consta de instrucciones y estado de ejecución. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Hilos Hilos 17 • En los sistemas operativos multihilo es posible crear tanto hilos como procesos. La diferencia estriba en que un proceso solamente puede crear hilos para sí mismo y en que dichos hilos comparten toda la memoria reservada para el proceso. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Hilos Hilos 18 • Un hilo tiene muchas similitudes con un proceso, aunque conceptualmente es un subconjunto de un proceso. Así, un proceso puede contener varios hilos pero un hilo no puede contener varios procesos. La diferencia más importante entre ambos reside en que un proceso tiene un espacio de memoria único que no puede ser accedido por otro proceso, a menos que se implemente un mecanismo de IPC (comunicación entre procesos). En el caso de los hilos, de manera intrínseca se tiene una región de memoria común a todos ellos (sección de datos, código y montículo). Así dentro de un proceso puede haber varios hilos de ejecución modificando la misma variable, sin necesidad de un programa adicional. Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Hilos Hilos 19 void funcion(void) { printf("Hilo %u \n", pthread_self()); sleep(2); pthread_exit(0); } int main(void) { pthread_t th1, th2; //Se crean dos hilos con los atributos predeterminados pthread_create(&th1,NULL,(void *)funcion,NULL); pthread_create(&th2,NULL,(void *)funcion,NULL); //Esperar a la terminación de ambos hilos pthread_join(th1,NULL); pthread_join(th2,NULL); Sistemas operativos II Clases 04 y 05 : Repaso de programación de sistemas basados en UNIX Hilos Hilos printf("Ha terminado el programa (hilo) principal\n"); exit(0); } 20