Introducció

En aquest tema, explorarem els conceptes de fils i processos, elements fonamentals en la gestió de la concurrència dins dels sistemes operatius. Entendre la diferència entre fils i processos, així com la seva gestió, és crucial per optimitzar el rendiment i la resposta dels sistemes.

Conceptes Clau

Processos

Un procés és un programa en execució, que inclou el codi del programa, les dades, els recursos i l'estat d'execució. Cada procés té el seu espai d'adreces, el que significa que la memòria utilitzada per un procés no és accessible per altres processos.

Característiques dels Processos:

  • Espai d'Adreces: Cada procés té el seu espai d'adreces independent.
  • Recursos: Cada procés té els seus propis recursos (fitxers oberts, dispositius, etc.).
  • Estat: Un procés pot estar en diferents estats com ara en execució, bloquejat o preparat.
  • PID (Process Identifier): Cada procés té un identificador únic.

Fils

Un fil (o thread) és la unitat bàsica d'execució dins d'un procés. Els fils comparteixen el mateix espai d'adreces i recursos del procés pare, però tenen els seus propis registres i pila.

Característiques dels Fils:

  • Compartició de Recursos: Els fils d'un mateix procés comparteixen recursos com ara memòria i fitxers oberts.
  • Execució Concurrent: Els fils poden executar-se de manera concurrent dins del mateix procés.
  • Menor Cost de Creació i Gestió: Crear i gestionar fils és més eficient que fer-ho amb processos.

Comparació entre Fils i Processos

Característica Processos Fils
Espai d'Adreces Separat Compartit
Recursos Independents Compartits
Cost de Creació Alt Baix
Comunicació Més complexa (IPC) Més senzilla (memòria compartida)
Robustesa Major (fallada aïllada) Menor (fallada afecta tot el procés)

Exemples Pràctics

Creació de Processos en C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        perror("fork failed");
        exit(1);
    } else if (pid == 0) {
        printf("This is the child process\n");
    } else {
        printf("This is the parent process\n");
    }

    return 0;
}

Explicació del Codi:

  • fork(): Crea un nou procés. El procés fill és una còpia del procés pare.
  • pid < 0: Indica que la creació del procés ha fallat.
  • pid == 0: Indica que el codi s'està executant en el procés fill.
  • pid > 0: Indica que el codi s'està executant en el procés pare.

Creació de Fils en C

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void* thread_function(void* arg) {
    printf("This is a thread\n");
    return NULL;
}

int main() {
    pthread_t thread;
    if (pthread_create(&thread, NULL, thread_function, NULL)) {
        perror("pthread_create failed");
        exit(1);
    }

    pthread_join(thread, NULL);
    return 0;
}

Explicació del Codi:

  • pthread_create(): Crea un nou fil.
  • pthread_join(): Espera que el fil acabi la seva execució.
  • thread_function(): Funció que s'executa en el nou fil.

Exercicis Pràctics

Exercici 1: Creació de Processos

Escriu un programa en C que creï dos processos fills i imprimeixi un missatge des de cada procés.

Solució:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    for (int i = 0; i < 2; i++) {
        pid_t pid = fork();

        if (pid < 0) {
            perror("fork failed");
            exit(1);
        } else if (pid == 0) {
            printf("This is child process %d\n", i);
            exit(0);
        }
    }

    for (int i = 0; i < 2; i++) {
        wait(NULL);
    }

    return 0;
}

Exercici 2: Creació de Fils

Escriu un programa en C que creï tres fils i imprimeixi un missatge des de cada fil.

Solució:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void* thread_function(void* arg) {
    int thread_num = *((int*)arg);
    printf("This is thread %d\n", thread_num);
    return NULL;
}

int main() {
    pthread_t threads[3];
    int thread_nums[3];

    for (int i = 0; i < 3; i++) {
        thread_nums[i] = i;
        if (pthread_create(&threads[i], NULL, thread_function, &thread_nums[i])) {
            perror("pthread_create failed");
            exit(1);
        }
    }

    for (int i = 0; i < 3; i++) {
        pthread_join(threads[i], NULL);
    }

    return 0;
}

Errors Comuns i Consells

Errors Comuns:

  • No gestionar correctament els errors de fork() o pthread_create(): Assegura't de comprovar els valors de retorn.
  • No esperar la finalització dels processos o fils: Utilitza wait() per processos i pthread_join() per fils.
  • Confusió entre espais d'adreces: Recorda que els processos tenen espais d'adreces separats, mentre que els fils comparteixen el mateix espai d'adreces.

Consells:

  • Utilitza identificadors únics: Assigna identificadors únics als processos i fils per facilitar el seguiment i la depuració.
  • Gestiona els recursos amb cura: Assegura't de tancar fitxers i alliberar memòria per evitar fuites de recursos.
  • Practica amb exemples: La millor manera d'aprendre és practicar amb exemples reals i experimentar amb diferents escenaris.

Conclusió

En aquesta secció, hem explorat els conceptes de fils i processos, les seves diferències, i com crear-los i gestionar-los en C. Comprendre aquests conceptes és fonamental per treballar amb sistemes operatius i desenvolupar aplicacions eficients i robustes. En el següent tema, aprofundirem en la sincronització i l'exclusió mútua, elements clau per gestionar la concurrència de manera segura.

© Copyright 2024. Tots els drets reservats