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
