You are on page 1of 9

INSTITUTO POLITÉCNICO NACIONAL

ESCUELA SUPERIOR DE CÓMPUTO


(ESCOM)

Asignatura: Sistemas Operativos.

Profesor: David Araujo Diaz.

Practica 3
Comunicación entre procesos/hilos.

Integrantes del equipo:

Buendia Velazco Abel.


No. de lista: 2.

Carpio Becerra Erick Gustavo.


No. de lista: 4.

Domínguez Páez Alejando Yael.


No. de lista: 9.

Portela Nájera Jesús Bambino.


No. de lista: 23.

Velázquez Diaz Luis Francisco.


No. de lista: 36.

Grupo: 4CM3.

Ciclo escolar 2023-B

1
Objetivo
Objetivo: Utilizar el mecanismo de memoria compartida para comunicar dos o más procesos en un
sistema operativo LINUX/UNIX.

Descripción
Se conoce por InterProcess Communication (IPC) al conjunto de mecanismos clave en los sistemas
Unix para llevar a cabo la intercomunicación o compartición de datos y sincronización entre distintos
procesos fácilmente.
Si bien actualmente Linux proporciona tres mecanismos IPC, en esta práctica nos centraremos en la
memoria compartida.

La memoria compartida es una forma implícita de comunicación entre procesos, y es muy eficiente
para este fin. Es un medio que permite establecer una zona común de memoria entre varias
aplicaciones.

La memoria convencional es asignada a un proceso a través de su espacio de direccionamiento virtual,


cualquier intento de acceso desde otro proceso resultará en una violación de segmento.
Por otro lado, el mecanismo de memoria compartida permite que dos o más procesos compartan un
segmento de memoria, lo que les permite acceder a los datos almacenados en él. Este método es el
más eficiente para la comunicación entre procesos.

Dado que la finalidad de la comunicación mediante memoria compartida es la transferencia de datos


entre procesos, los programas que utilizan este mecanismo suelen establecer protocolos de bloqueo,
como el uso de semáforos, que a su vez es otro tipo de comunicación (sincronización) entre procesos.

Tanto la memoria asignada a un proceso como la compartida son virtuales, lo que significa que su
dirección física puede cambiar con el tiempo. Sin embargo, esto no plantea ningún problema ya que los
procesos no hacen referencia a direcciones físicas sino virtuales, y es el núcleo del sistema operativo,
a través de su gestor de memoria, el encargado de traducirlas de una a otra.

El sistema tiene la capacidad de soportar varias regiones compartidas, cada una de las cuales es

2
accesible por un subconjunto de procesos, lo que permite una comunicación eficiente entre ellos.
Además, cada proceso puede acceder a varias regiones compartidas en el espacio de
direccionamiento virtual, lo que aumenta la flexibilidad y eficacia de la comunicación entre procesos.

Existen cuatro llamadas al sistema que se usan para trabajar con memoria compartida:

shmget()
Permite acceder a una zona de memoria compartida y, opcionalmente, crearla en caso de no existir.
Esta llamada requiere tres argumentos: clave, tamaño del segmento y el flag inicial de operación
(shmflg). Devuelve un entero llamado shmid, que se utiliza para hacer referencia al segmento.

Cabe mencionar que shmget() únicamente reserva el espacio necesario para albergar el segmento,
pues este no se crea hasta que algún proceso se asigne a él. La posición de memoria final la decide,
en principio el sistema.
También, si se emplea para obtener una referencia a una zona de memoria compartida que ya existe,
el tamaño especificado debe ser inferior o igual al de la memoria existente, pues de otro modo, el
tamaño asignado debe ser múltiplo de PAGE_SIZE (tamaño de una página de memoria, es decir, 4KB
en la arquitectura x86)
El valor de shmflg se compone de:
IPC_CREAT: Crea un nuevo segmento. Si este flag no se precisa, shmget() solamente buscará el
segmento asociado con la clave y comprobará si el usuario tiene permisos para acceder a este.
IPC_EXCL: Junto a IPC_CREAT, se usa para asegurar el fallo si el segmento no existe.
mode_flags: Los nueve bits menos significativos del número están reservados para el establecimiento
de permisos de acceso. Por ahora los permisos de ejecución no son utilizados por el sistema.

Estructura de la utilización de shmget():


#include <sys/ipc.h>
#include <sys/shm.h>
Int shmget (key_t key, size_t size, int shmflg);

shmat()
Debe invocar un proceso para adjuntar una zona de memoria compartida dentro de su espacio de
3
direcciones. Requiere tres parámetros: identificador del segmento (shmid), una dirección de memoria
(shmaddr) y banderas (option). En caso de que se indique NULL en la dirección, el sistema operativo
asignará una posición de memoria libre. Devuelve la dirección de comienzo del segmento de memoria
asignado y se actualizan los siguientes campos de la estructura shmid_kernel: shm_atim (recibe la
fecha actual), shm_lprid (recibe el pid del proceso que llama) y shm_nattch (incrementa en una
unidad).
En option puede especificarse:
SHM_RND: Aquí el sistema intentara vincular la zona de memoria a una dirección múltiplo de SHMLBA
(shmparam.h) lo más próxima posible a la especificada.
SHM_RDONLY: Esta dejará que el proceso sólo pueda acceder al segmento de memoria en lectura.
En caso de no especificarse, el segmento se vinculará tanto en modo lectura, como en escritura.

Estructura de la utilización de shmat():


#include <sys/types.h>
#include <sys/shm.h>
*void shmat (int shmid, const void *shmaddr, int option);

shmdt()
Esta operación realiza el proceso de shmat() para desvincularse de una zona de memoria compartida.
Entonces, únicamente requiere como parámetro la dirección shmaddr de la zona en cuestión.
El resultado de esta llamada al sistema, será la actualización de estos campos de la estructura
shmid_kernel: shm_dtim (recibe la fecha actual), shm_lprid (recibe el pid del proceso que llama) y
shm_nattch (queda decrementado en una unidad).

Estructura de la utilización de shmdt():


#include <sys/shm.h>
#include <sys/types.h>
Int shmdt (void *shmaddr);

shmctl()
Manipula varios parámetros asociados con la memoria compartida a través de cmd.

4
Entre las operaciones disponibles se encuentran:
IPC_STAT: Lee el estado de la estructura de control de la memoria asociada a shmid y lo devuelve a
través de la estructura de datos apuntada por buf.
IPC_SET: Modifica el valor de los siguientes miembros de la estructura de datos asociada a shmid con
el correspondiente valor encontrado en la estructura apuntada por buf: shm_perm.uid, shm_perm.gid y
shm_perm.mode
IPC_RMID: Señala una región de memoria compartida como destruida, aunque el borrado sólo se hace
efectivo cuando el último proceso que la adjuntaba deje de hacerlo. En caso de que cuando se realice
la invocación, el segmento aún esté asignado a otro proceso, la clave será puesta a IPC_PRIVATE.
SHM_LOCK: Bloquea la zona de memoria compartida especificada por shmid. El segmento es grabado
en memoria, por lo que no es posible borrarlo a partir de esta operación. De igual forma, tampoco se
podrá hacer swapping sobre él. Esta cmd solo puede ser ejecutada por un proceso que tenga un ID de
usuario efectivo igual al del superusuario. De esta forma asegura la permanencia de los datos en la
memoria.
SHM_UNLOCK: Desbloquea la región de memoria compartida especificada por shmid. Así como
SHM_LOCK, esta operación sólo la podrán ejecutar aquellos procesos con privilegios de acceso
adecuados.

Estructura de la utilización de shmctl():


#include <sys/ipc.h>
#include <sys/shm.h>
Int shmctl (int shmid, int cmd, struct shmid_ds *buf);

Prueba de escritorio
En el programa propuesto para esta práctica, el algoritmo tendrá que realizar los siguientes pasos:
1) Se define la constante SHMSIZE con valor 1024.
2) Se declara la variable shmid de tipo int.
3) Se declara la variable key de tipo key_t y se le asigna el valor 1234.
4) Se declara el puntero shm de tipo char.
5) Se declara el puntero s de tipo char.
6) Se llama a la función shmget para crear un segmento de memoria compartida con la clave key y

5
el tamaño SHMSIZE. Si la llamada devuelve un valor negativo, se muestra un mensaje de error
y se sale del programa.
7) Se llama a la función shmat para adjuntar el segmento de memoria compartida al espacio de
direcciones del proceso. Si la llamada devuelve un puntero igual a -1, se muestra un mensaje de
error y se sale del programa.
8) Se inicializa el puntero s con el valor de shm.
9) Se recorre un ciclo desde la letra 'a' hasta la letra 'z' y se va escribiendo cada letra en el
segmento de memoria compartida a través del puntero s.
10) Se escribe el caracter nulo '\0' en la posición apuntada por el puntero s.
11) Se recorre otro ciclo para leer cada letra escrita en el segmento de memoria compartida a través
del puntero s y se va mostrando cada letra por pantalla con la función putchar.
12) Se llama a la función shmdt para desenlazar el segmento de memoria compartida del espacio de
direcciones del proceso.
13) Se llama a la función shmctl para eliminar el segmento de memoria compartida.

Código fuente
El programa crea un segmento de memoria compartida con la clave 1234 y el tamaño 1024 bytes,
escribe las letras del alfabeto en el segmento y las lee de vuelta para imprimir en pantalla, y luego
libera y elimina el segmento de memoria compartida.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

// Estableciendo el tamaño del segmento de memoria compartida


#define SHMSIZE 1024

int main()
{
int shmid;
key_t key;
char *shm, *s;

key = 1234;

// Crear el segmento de memoria compartida


if ((shmid = shmget(key, SHMSIZE, IPC_CREAT | 0666)) < 0) {
perror("shmget");

6
exit(1);
}

// Adjuntar el segmento de memoria compartida al espacio de direcciones del proceso


if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat");
exit(1);
}

// Escribir datos en la memoria compartida


s = shm;
for (char c = 'a'; c <= 'z'; c++) {
*s++ = c;
}
*s = '\0';

// Leer datos desde la memoria compartida


for (s = shm; *s != '\0'; s++) {
putchar(*s);
}
putchar('\n');

// Desenlazar el segmento de memoria compartida


shmdt(shm);

// Eliminar el segmento de memoria compartida


shmctl(shmid, IPC_RMID, NULL);

return 0;
}

Prueba de pantalla

Conclusiones
El mecanismo de memoria compartida es una forma eficiente de comunicación entre procesos en
sistemas operativos como Linux/UNIX. Este mecanismo permite a varios procesos acceder a la misma
zona de memoria compartida, lo que les permite compartir datos e información de manera rápida y

7
eficiente sin tener que recurrir a la copia de datos entre procesos.
La memoria compartida se crea mediante la asignación de un segmento de memoria compartida que
se puede acceder desde varios procesos simultáneamente. Los procesos pueden leer y escribir datos
en esta zona de memoria compartida como si fuera su propia memoria privada. El mecanismo de
memoria compartida se utiliza comúnmente para compartir datos entre procesos relacionados, como
procesos de un mismo programa o procesos que realizan una tarea en común.
Aunque el mecanismo de memoria compartida es eficiente, es importante tener en cuenta que el
acceso concurrente a una zona de memoria compartida puede generar problemas de sincronización y
conflicto. Es necesario implementar técnicas de sincronización y exclusión mutua para garantizar que
los procesos no accedan simultáneamente a la misma área de memoria y se produzcan errores en los
datos compartidos.
En conclusión, el mecanismo de memoria compartida es una herramienta poderosa para la
comunicación entre procesos en sistemas operativos como Linux/UNIX. Permite compartir datos de
manera eficiente y rápida, pero es importante tener en cuenta los problemas de sincronización y
exclusión mutua que pueden surgir al trabajar con múltiples procesos en una misma área de memoria
compartida.

8
Bibliografía

"Lección 24 Memoria compartida". Servidor deInformación de Sistemas Operativos -


ULPGC. http://sopa.dis.ulpgc.es/ii-dso/leclinux/ipc/mem_compartida/lec24_memcomp.pdf (accedido el
18 de marzo de 2023).

"Memoria Compartida" Bufer. https://w3.ual.es/~rguirado/so/practica5 (accedido el 18 de marzo de


2023).

You might also like