cambios 2024-11-04 10:33:39

This commit is contained in:
Jose
2024-11-04 10:33:39 +01:00
3 changed files with 97 additions and 13 deletions

View File

@@ -226,21 +226,74 @@ En C/C++ parece fácil: usándolo. La mayoría de SO están escritos en C así q
- Funciones terminadas en W (`MessageBoxW`)
### <mark style="background: #FFB86CA6;">Tratamiento de errores</mark>
Las funciones devuelven un entero, y si este es negativo es que ha terminado con error. Para más información sobre el error se usa `GetLastError()` y para mensajes al usuario `FormatMessage()`.
# <mark style="background: #FFF3A3A6;">TEMA 5: Control de ejecución: procesos e hilos</mark>
En Windows todos los procesos tienen al menos el "main thread". El programa termina cuando termina el hilo principal. Dos modelos básicos:
- **Multihilo:** cada proceso tiene múltiples hilos. Típico de Windows aunque se usa cada vez más en UNIX/Linux.
# <mark style="background: #FFF3A3A6;">TEMA 5: Control de ejecución: procesos e threads</mark>
En Windows todos los procesos tienen al menos el "main thread". El programa termina cuando termina el thread principal. Dos modelos básicos:
- **Multithread:** cada proceso tiene múltiples threads. Típico de Windows aunque se usa cada vez más en UNIX/Linux.
- **Multiproceso:** múltiples procesos. Típico de UNIX/Linux, aunque también se puede en Windows. En Linux es **muy fácil** usando `fork()`.
## <mark style="background: #ADCCFFA6;">1. Operaciones básicas con hilos</mark>
Organizar la ejecución en varios hilos **¿para qué?**
## <mark style="background: #ADCCFFA6;">1. Operaciones básicas con threads</mark>
Organizar la ejecución en varios threads **¿para qué?**
EJEMPLO: Programa de proceso de audio
- **Hilo 1:** lee datos de la entrada de audio, los procesa y envía el resultado a la salida.
- **thread 1:** lee datos de la entrada de audio, los procesa y envía el resultado a la salida.
- Periódico
- Intensivo en datos
- Requiere velocidad de proceso
- **WORKER THREADS**
- **Hilo 2:** controla la UI (subir, bajar volumen, play, pause...) Complicado si alguna tarea es bloqueante.
- **thread 2:** controla la UI (subir, bajar volumen, play, pause...) Complicado si alguna tarea es bloqueante.
- No periódico
- No intensivo
- No requiere velocidad de proceso
- **USER INTERFACE THREAD**
-
### <mark style="background: #FFB86CA6;">Crear un thread</mark>
En Windows se usa `CreateThread()` que devuelve un `HANDLE`. Los elementos que integran el thread son:
- Función de entrada
- Parámetro(s)
- Pila
- Almacenamiento local al thread
- El HANDLE y el ID
Los threads son **asíncronos**.
#### <mark style="background: #D2B3FFA6;">Ejemplo</mark>
```C
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "Spanish");
  
DWORD Ciclo = 1000; // Ciclo entre pitidos (en ms)
DWORD Frecuencia = 500;
DWORD Duracion = 100;
while (TRUE){
// bip a frec. y duración que se le pasa
Beep(Frecuencia, Duracion);
Sleep(Ciclo);
}
printf("\nPulse tecla RETORNO para terminar\n");
getchar();  // bloqueo
return 0;
}
```
Para evitar el bloqueo, en C++ existen alternativas (en C **NO**), como `std::thread` o `std::async`.
### <mark style="background: #FFB86CA6;">Suspender/Reactivar un thread</mark>
El thread se puede suspender o reactivar usando respectivamente `SuspendThread` y `ResumeThread`. El thread está suspendido si el contador != 0.
### <mark style="background: #FFB86CA6;">Terminar un thread</mark>
Un thread finaliza cuando termina su función de entrada, cuando se termina a sí mismo con `ExitThread` o cuando lo "terminan" con `TerminateThread`.
## <mark style="background: #ADCCFFA6;">2. Organización de los datos en un thread</mark>
Los hilos comparten variables globales y código. También pueden pasarse punteros (posibilidad de errores).
### <mark style="background: #FFB86CA6;">Código reentrante</mark>
Código que puede ser usado desde más de un hilo. Se puede aplicar a:
- Código completo del hilo
- Algunas funciones
- Bibliotecas
Cada instancia de un thread tiene sus propios recursos, los cuales hay que proteger con mecanismos de control de la concurrencia.
## <mark style="background: #ADCCFFA6;">3. Creando procesos</mark>
`CreateProcess` crea un proceso concurrente. Algunos puntos a destacar en la descripción de `CreateProcess`:
- **`IpApplicationName`**: es opcional. Si es `NULL`, el nombre del programa se incluye en el siguiente parámetro.
- **`IpCommandLine`**: si el path del ejecutable no está, se sigue la secuencia de búsqueda que viene al final de este parámetro.
- **`IpProcessAttributes, IpThreadAttributes, bInheritHandles, IpEnvironment, IpCurrentDirectory`**: <strong style="color:red;">no los usaremos</strong>, poner a NULL/FALSE.
- **`IpStartupInfo`**: la estructura `STARTUPINFO` <strong style="color:red;">no la usaremos</strong> pero tiene que estar.
- **`IpProcessInformation`**: rellena la estructura `PROCESS_INFORMATION` con información sobre el proceso y thread creado (handles, process/threads ids).
## <mark style="background: #ADCCFFA6;">4. Punto de vista de la programación y procesos POSIX</mark>
- Aunque el proceso creado se le llama "hijo" **no hay relación lógica** entre ambos, al menos en Windows. En UNIX/Linux/POSIX **sí hay**.
- La creación del proceso es asíncrona, **NO** es una "llamada".
- En la biblioteca de C: `exec` (UNIX) / `_exec` (Win) funcionan distinto en Windows y UNIX/Linux. En Windows se basa en `CreateProcess` y en UNIX/Linux el proceso actual carga un nuevo programa:
- `posix spawn` es lo equivalente a `CreateProcess` que básicamente hace: `fork` + `exec`