Skip to content

Commit

Permalink
feat: versiones resumidas de contenidos
Browse files Browse the repository at this point in the history
  • Loading branch information
jesustorresdev committed Jul 3, 2023
1 parent e8e02a5 commit fe66718
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 0 deletions.
135 changes: 135 additions & 0 deletions src/cap09/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Operaciones sobre los procesos

## Uso de fork()

La función `fork()` se utiliza para crear un nuevo proceso.
El proceso creado es una copia exacta del proceso que llamó a `fork()`, pero tiene su propio espacio de direcciones.

```c
#include <unistd.h>

pid_t pid = fork();

if (pid < 0) {
// Error al crear el proceso.
} else if (pid == 0) {
// Este bloque se ejecutará en el proceso hijo.
} else {
// Este bloque se ejecutará en el proceso padre.
}
```

El archivo [fork.c](fork.c) contiene un ejemplo del uso de `fork()`.

## Uso de exec()

La función `exec()` se utiliza para reemplazar la imagen del proceso actual con un nuevo programa.
La función `exec()` solo retorna de su invocación si hay un error.

```c
#include <unistd.h>

if (pid < 0) {
// Error al crear el proceso.
} else if (pid == 0) {
// En el proceso hijo, ejecutamos otro programa.
execl("/path/to/program", "program", (char *)NULL);

// Si llegamos aquí, hubo un error al ejecutar exec.
} else {
// Este bloque se ejecutará en el proceso padre.
}
```

El archivo [fork-exec.c](fork-exec.c) contiene un ejemplo del uso de `fork()` y `exec()` para ejecutar otro proceso con otro programa.

## Uso de wait() y waitpid()

Las funciones `wait()` y `waitpid()` se utilizan para hacer que el proceso padre espere a que termine uno de sus procesos hijos.

```c
#include <sys/wait.h>
#include <unistd.h>

int status;

if (pid < 0) {
// Error al crear el proceso.
} else if (pid == 0) {
// En el proceso hijo, ejecutamos otro programa.
execl("/path/to/program", "program", (char *)NULL);

// Si llegamos aquí, hubo un error al ejecutar exec.
} else {
// En el proceso padre, esperamos a que termine el hijo.
wait(&status);
}
```

La función `wait()` retorna cuando termina alguno de los procesos hijos del procesos que la llamó.
Para esperar a un proceso hijo específico, podemos usar `waitpid()`.

```c
#include <sys/wait.h>

pid_t pid = fork();

if (pid == 0) {
// En el proceso hijo
} else {
int status;
// En el proceso padre, esperamos a que termine el hijo específico.
waitpid(pid, &status, 0);
}
```

## Terminación del programa

Para terminar un programa, simplemente usamos la función `return` desde la función `main()`.
También podemos usar la función `exit()` desde cualquier parte del programa para terminarlo inmediatamente.

```c
#include <stdlib.h>

if (alguna_condicion_de_error) {
exit(1); // Termina el programa con un código de error.
}
```

El valor indicado en `exit()` o `return` lo puede leer el padre al volver de `wait()` o `waitpid()` usando la macro `WEXITSTATUS()` sobre el valor de `status`

```c
#include <sys/wait.h>

pid_t pid = fork();

if (pid == 0) {
// En el proceso hijo
} else {
int status;
// En el proceso padre, esperamos a que termine el hijo específico.
waitpid(pid, &status, 0);
int child_exit_status = WEXITSTATUS(status);
}
```

## Errores en las llamadas al sistema

Cualquiera de las anteriores llamadas al sistema puede fallar.
Para manejar errores en las llamadas al sistema, normalmente comprobamos el valor de retorno de la llamada al sistema.
Si es negativo, es que ocurrió un error y la variable `errno` contiene el código de error.

```c
#include <errno.h
#include <stdio.h>
#include <unistd.h>

pid_t pid = fork();

if (pid < 0) {
fprintf(stderr, "Fallo en fork: %s\n", strerror(errno));
return 1; // Termina el programa con un código de error.
}
```

La función `strerror()` permite obtener un mensaje descriptivo del código de error indicado.
72 changes: 72 additions & 0 deletions src/cap17/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Archivos mapeados en memoria

El mapeo de archivos en memoria es una técnica eficiente que permite a los programas acceder a los datos en un archivo como si fueran una matriz en memoria.
Esto se realiza con las llamadas al sistema `mmap()` y `munmap()`.

## Uso de mmap()

La función `mmap()` mapea un archivo en el espacio de direcciones de un proceso.
Aquí se muestra un ejemplo de cómo mapear un archivo en memoria:

```c
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

// Primero se abre el archivo, con los permisos adecuados.
int fd = open("archivo.txt", O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Fallo al abrir el archivo: %s\n", strerror(errno));
return 1;
}

// Se usa fstat() para obtener el tamaño del archivo porque a mmap() hay que indicarle
// el tamaño de la porción del archivo que queremos mapear.
struct stat st;
if (fstat(fd, &st) < 0) {
fprintf(stderr, "Fallo en fstat: %s\n", strerror(errno));
return 1;
}

void *map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
fprintf(stderr, "Fallo en mmap: %s\n", strerror(errno));
return 1;
}

// Ahora se puede acceder a los datos del archivo como si estuvieran en la memoria:
// Por ejemplo, imprimir los primeros 10 caracteres por la consola.
for (int i = 0; i < 10 && i < st.st_size; i++) {
printf("%c", ((char*)map)[i]);
}
```

## Uso de munmap()

Una vez que hayas terminado de trabajar con el mapeo en memoria, se debe liberar con `munmap()`:

```c
if (munmap(map, st.st_size) < 0) {
fprintf(stderr, "Fallo en munmap: %s\n", strerror(errno));
return 1;
}
```

Y tampoco se debe olvidar cerrar el descriptor del archivo cuando se haya terminado:

```c
if (close(fd) < 0) {
fprintf(stderr, "Fallo al cerrar el archivo: %s\n", strerror(errno));
return 1;
}
```

## Ejemplos

El archivo [mmapped-files.c](mmapped-files.c) contiene un ejemplo del uso de `mmap()` y `munmap()` para hacer la copia de un archivo.
El archivo [mmapped-files.cpp](mmapped-files.cpp) contiene un ejemplo similar pero en C++, usando la clase `memory_map` definida en [memory_map.hpp](memory_map.hpp)

0 comments on commit fe66718

Please sign in to comment.