Una computadora con un solo CPU puede ejecutar solamente una instrucción a la vez, si un proceso
está ejecutando un programa de usuario en modo usuario y necesita un servicio del sistema (como
leer o guardar los datos de un archivo) tiene que ejecutar una instrucción de trap para transferir el
control al SO (porque es el SO el que se encargará de ejecutar el servicio solicitado). El SO
averigua que es lo que quiere el proceso para lo cual inspecciona los parámetros, lleva a cabo la
llamada al sistema y devuelve el control a la instrucción que va después de la llamada al sistema. En
cierto modo una llamada al sistema es similar a una llamada a un procedimiento solo que las
llamadas al sistema entran al KERNEL y las llamadas a procedimientos no.
Veremos por ejemplo una llamada al sistema para leer archivos, la llamada read posee tres
parámetros el primero especifica el archivo, el segundo apunta al búfer y el tercero proporciona el
número de bytes a leer, al igual que casi todas las llamadas al sistema la misma en invocada desde
programas en C mediante una llamada a un procedimiento de la biblioteca con el mismo nombre
que llamada al sistema (read). Una llamada desde un programa en C podría tener la siguiente
apariencia:
cuenta = read(fd, bufer, nbytes);
esta llamada devuelve el número de bytes que se leen en cuenta que por lo general es el mismo
número aunque puede ser menor si se encuentra el final del archivo pero, si no se puede llevar a
cabo la llamada al sistema cuenta se establece a – y el número de error se coloca en una variable
global llamada errno. En la figura 2 se resumen los pasos detallados que ocurren al ejecutar la
llamada al sistema read para cuenta.
Figura 2. Los 11 pasos para realizar la llamada al sistema read(fb, bufer, nbytes).
Llamada Descripción
pid* = fork() Crea un proceso hijo, idéntico al padre.
pid = waitpid(pid, &statloc, opciones) Espera a que un hijo termine
s = execve(nombre, argv, enornp) Reemplaza la imagen del núcleo de un proceso
exit(estado) Termina la ejecución de un proceso y devuelve el estado
* pid es un id de proceso.
Llamada Descripción
fd=open(archivo, como, …) Abre un archivo para lectura, escritura o ambas
s=close(fd) Cierra un archivo abierto
n=read(fd, bufer, nbytes) Lee datos de n archivo y los coloca en un búfer
n=write(fd, bufer, nbytes) Escribe datos de un búfer a un archivo
posicion=Iseek(fd, desplazamiento, dedonde) Desplaza el apuntador del archivo
s=stat(nombre, &buf) Obtiene la información de estado de un archivo
fd es un descriptor de archivo, n es una cuenta de bytes, posicion es un desplazamiento dentro del
archivo.
Llamada Descripción
s=chdir(nombredir) Cambia el directorio de trabajo
s=chmod(nombre, modo) Cambia los bits de protección de un archivo
s=kill(pid, senial) Envía una señal a un proceso
segundos=tiempo(&segundos) Obtiene el tiempo transcurrido desde 1/1/1970
Segundos es el tiempo transcurrido
En la figura 3 se muestra el código que simula el comportamiento del SHELL cabe recordar que en
el SHELL una instrucción debe esperar a la que se está ejecutando termine para poder empezar.
En UNIX los procesos tienen la memoria divida en tres segmentos (figura 4): Segmento de texto
(código del programa), segmento de datos (variables) y segmento de pila.
Figura 4. División de la memoria por un proceso en POSIX.
En sistemas *NIX los archivos cuentan con una llamada stat (El archivo esta cerrado) o fstat (el
archivo esta abierto) el cual recibiendo el archivo y un apuntador a una estructura de salida, facilita
la metadata del mismo en la figura 5 podemos ver la salida de stat en terminal para [este archivo.
Figura 5. Salida de stat en shell ubuntu 18.04
LLAMADAS AL SISTEMA PARA ADMINISTRAR DIRECTORIOS
En la tabla 3 resumíamos las llamadas al sistema mas comunes para trabajar con directorios junto a
una pequeña descripción en la que hemos de ahondar en éste apartado.
• Mkdir y rmdir son usados para crear y eliminar directorios con la particularidad que al
crearse un directorio el mismo se encuentra vacío y para poder eliminar uno con rmdir
también debe estar vacío.
• Link permite al archivo aparecer bajo dos o mas nombres (a menudo en directorios distintos)
este comando permite compartir un mismo archivo, es decir que los cambios que cada
persona que posea acceso ala rchivo compartido haga, los mismos se reflejarán en las copias
compartidas del resto de usuarios. Esta es una diferencia con las copias creadas ya que un
cambio en una copia no altera las demás copias existentes. Un ejemplo podría ser enlazar el
archivo “lista_de_anime” del usaurio Pablo a un archivo “anime” del usuario Yohana:
API DE WINDOWS 32
En cuanto a llamadas al sistema windows y UNIX es muy diferente, mientras que en UNIX
poseemos llamadas al sistema que ocasionan trap en windows no sucede así, las interacciones de
llamadas con el kernel son casi inexistentes para el usaurio y todo se maneja a nivel de
procedimientos propios de Windows.
Windows utiliza un modelo de programación basado en eventos y ha definido un conjunto de
procedimientos llamados API Win32 (Interfaz de programación de aplicaciones) que los
programadores usan para tener acceso a los servicios del sistema (no es un acceso directo sino
mediante el api que sirve de intermediario). El número de llamadas llega a los miles y de versión a
versión una de estas llamadas puede que se ejecute enteramente en espacio de usuario mientras que
en otra involucre el modo de sistema.
Entre Windows y UNIX incluso existen diferencias en cuales llamadas son posibles realizar, en la
mostramos figura 6 mostramos llamadas a UNIX con su apenas correspondiente llamada en
windows.
Figura 6. Llamadas a UNIX y a WINDOWS que son similares en conceptualización.
PIPES EN *NIX Y WINDOWS
En informática una tubería (pipe) consiste en una cadena de procesos conectados de tal forma que la
salida de uno sea la entrada del próximo. Es como ejecutar un comando, almacenar la salida en un
archivo temporal y luego usar el archivo temporal como parámetro de entrada de otro comando.
Los pipes permiten la comunicación y sincronización entre procesos y es muy común hacerlo
mediante buffers de datos entre elementos consecutivos.
De manera formal permite conectar la salida estándar de un programa con la entrada estándar de
otro.
Por ejemplo queremos listar elementos de un directorio de forma ordenada (en unix):
LS | SORT
LS por si solo muestra en salida estándar el contenido de un directorio.
SORT permite ordenar de manera alfabética los parámetros recibidos.
Al usar un pipe la salida de ls es la entrada de sort
Veamos ahora un ejemplo en powershell/cmd, digamos que queremos revisar los procesos pero esto
es un tanto engorroso por la cantidad de los mismos, entonces usamos la salida de los procesos y
pedimos que se muestren pantalla a pantalla:
Get-Process | more
Get-Process me muestra todos los procesos.
More me permite dividir la salida estándar en pantallas.
Al usar un pipe mezclo estas dos funcionalidades a mi favor.
• TEE: A diferencia de CAT, TEE permite copiar los datos que recibe de entrada estandar a
cero o más archivos indicados por el usuario es necesario usar | antes del tee y luego de
generar la entrada estandar para el procedimiento que pretendemos realizar. TEE Esta
relacionado con el concepto de tuberías. (ejemplo usar tee con ls y con cat).
• PS: Retorna los procesos activos.
• MORE: Type muestra le contenido tal como va leyendo byte a byte lo que dificulta la
visualización del mismo, MORE permite mostrar el contenido de un archivo pero pantalla a
pantalla.
• CLS: Limpia la consola.
RECURSOS