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()
opthread_create()
: Assegura't de comprovar els valors de retorn. - No esperar la finalització dels processos o fils: Utilitza
wait()
per processos ipthread_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.
Fonaments de Sistemes Operatius
Mòdul 1: Introducció als Sistemes Operatius
- Conceptes Bàsics de Sistemes Operatius
- Història i Evolució dels Sistemes Operatius
- Tipus de Sistemes Operatius
- Funcions Principals d'un Sistema Operatiu
Mòdul 2: Gestió de Recursos
Mòdul 3: Concurrència
- Conceptes de Concurrència
- Fils i Processos
- Sincronització i Exclusió Mútua
- Problemes Clàssics de Concurrència