Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Système D'exploitation Producer Consumer Problem

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 13

qwertyuiopasdfghjklzxcvbnmq

wertyuiopasdfghjklzxcvbnmqwe
rtyuiopasdfghjklzxcvbnmqwerty
Système d’exploitation

uiopasdfghjklzxcvbnmqwertyuio
Producer Consumer problem

pasdfghjklzxcvbnmqwertyuiopas
Hana djemil,Benterzi youssra,………..zineb

dfghjklzxcvbnmqwertyuiopasdfg
hjklzxcvbnmqwertyuiopasdfghjk
lzxcvbnmqwertyuiopasdfghjklzx
cvbnmqwertyuiopasdfghjklzxcvb
nmqwertyuiopasdfghjklzxcvbnm
qwertyuiopasdfghjklzxcvbnmqw
ertyuiopasdfghjklzxcvbnmqwert
yuiopasdfghjklzxcvbnmqwertyui
1.Code :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <semaphore.h>

#define BUFFER_SIZE 4

// Shared memory structure


struct SharedMemory {
int buffer[BUFFER_SIZE];
sem_t mutex;
sem_t empty_slots;
sem_t filled_slots;
};

// Producer function
void producer(int class_id, struct SharedMemory *shared_memory)
{
while (1) {
// Produce item
int item = 1; // Replace this with the actual item produced

// Acquire empty slot


sem_wait(&shared_memory->empty_slots);

// Acquire mutex to update the buffer


sem_wait(&shared_memory->mutex);

// Update buffer
shared_memory->buffer[class_id - 1] = item;

// Release mutex
sem_post(&shared_memory->mutex);

// Signal that a slot is filled


sem_post(&shared_memory->filled_slots);

// Simulate some time taken for production


sleep(1);
}
}

// Consumer function
void consumer(int class_id, struct SharedMemory
*shared_memory) {
while (1) {
// Acquire filled slot
sem_wait(&shared_memory->filled_slots);

// Acquire mutex to access buffer


sem_wait(&shared_memory->mutex);

// Consume item
int item = shared_memory->buffer[class_id - 1];

// Release mutex
sem_post(&shared_memory->mutex);

// Signal that a slot is empty


sem_post(&shared_memory->empty_slots);

// Process or use the consumed item


printf("Consumer %d consumed: %d\n", class_id, item);

// Simulate some time taken for consumption


sleep(1);
}
}

int main() {
// Create shared memory
int shmid = shmget(IPC_PRIVATE, sizeof(struct
SharedMemory), IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(EXIT_FAILURE);
}

// Attach the shared memory


struct SharedMemory *shared_memory = shmat(shmid, NULL,
0);
if (shared_memory == (struct SharedMemory *)-1) {
perror("shmat");
exit(EXIT_FAILURE);
}

// Initialize semaphores
sem_init(&shared_memory->mutex, 1, 1);
sem_init(&shared_memory->empty_slots, 1, BUFFER_SIZE);
sem_init(&shared_memory->filled_slots, 1, 0);

// Fork processes
pid_t p1 = fork();
pid_t p2 = fork();
pid_t p3 = fork();
pid_t p4 = fork();

if (p1 == 0 || p2 == 0 || p3 == 0 || p4 == 0) {
// Child processes - producers
int class_id = (p1 == 0 || p2 == 0) ? 1 : 2;
producer(class_id, shared_memory);
exit(0);
} else {
// Parent process - consumers
pid_t c1 = fork();
pid_t c2 = fork();

if (c1 == 0 || c2 == 0) {
// Child processes - consumers
int class_id = (c1 == 0) ? 1 : 2;
consumer(class_id, shared_memory);
exit(0);
} else {
// Parent process - wait for all processes to finish
wait(NULL);
wait(NULL);
wait(NULL);
wait(NULL);
wait(NULL);
wait(NULL);
// Detach and remove shared memory
shmdt(shared_memory);
shmctl(shmid, IPC_RMID, NULL);
}
}

return 0;
}

THE OUTPUT :

RAPPORT :
**Rapport sur le Code : Système de Producteur-Consommateur
avec Mémoire Partagée et Sémaphores**

Ce code en langage C implémente un problème classique de


producteur-consommateur en utilisant la mémoire partagée et les
sémaphores. Le problème du producteur-consommateur est un
scénario de synchronisation entre plusieurs processus où certains
produisent des données (producteurs) et d'autres les consomment
(consommateurs).

**Structure de la Mémoire Partagée :**

Le code utilise une structure `SharedMemory` qui comprend un


tableau `buffer` de taille `BUFFER_SIZE` pour stocker les éléments
produits par les producteurs. Il utilise également trois sémaphores
pour la synchronisation : `mutex` pour l'accès exclusif au buffer,
`empty_slots` pour le suivi des emplacements vides dans le buffer, et
`filled_slots` pour le suivi des emplacements remplis.

**Fonction Producteur :**

La fonction `producer` simule la production d'un élément


(actuellement défini comme `item = 1`). Elle utilise les sémaphores
pour garantir qu'elle acquiert un emplacement vide dans le buffer, met
à jour le buffer de manière sécurisée avec le mutex, et signale qu'un
emplacement est maintenant rempli. Elle termine ensuite avec une
pause d'une seconde pour simuler le temps de production.

**Fonction Consommateur :**

La fonction `consumer` acquiert un emplacement rempli dans le


buffer à l'aide de la sémaphore `filled_slots`. Elle utilise également le
mutex pour un accès exclusif au buffer, consomme l'élément, signale
qu'un emplacement est maintenant vide avec la sémaphore
`empty_slots`, puis traite ou utilise l'élément consommé. Comme le
producteur, le consommateur termine avec une pause d'une seconde
pour simuler le temps de consommation.

**Fonction Principale (main) :**

La fonction principale commence par créer et attacher la mémoire


partagée, initialise les sémaphores, puis fork plusieurs processus pour
représenter les producteurs et les consommateurs. Le nombre de
producteurs et de consommateurs est actuellement défini à deux
chacun, mais cela peut être ajusté en fonction des besoins.

**Fork/Join :**
Le modèle de programmation utilisé dans ce code est basé sur la
création de processus par le biais de la fonction système `fork()` et la
synchronisation de ces processus à l'aide de la fonction `wait()`, ce qui
est souvent appelé le modèle "fork and join" ou "fork and wait".

1. **Fork :**
La fonction `fork()` est utilisée pour créer un nouveau processus
en duplicant le processus appelant. Dans le code fourni, plusieurs
forks sont utilisés pour créer un certain nombre de producteurs et de
consommateurs. Le nouvellement créé processus hérite du code, des
données et de l'espace mémoire du processus parent. Cependant,
chaque processus a son propre espace d'adressage et s'exécute de
manière indépendante des autres processus.

Par exemple, dans la fonction principale (`main()`), il y a quatre


forks (`p1`, `p2`, `p3`, `p4`) pour créer quatre producteurs, et deux
forks (`c1`, `c2`) pour créer deux consommateurs.

V 2. **Join (Wait) :**


La fonction `wait()` est utilisée pour que le processus parent
attende la fin de l'exécution de ses processus enfants. Cette fonction
bloque le processus appelant jusqu'à ce qu'un de ses processus enfants
se termine. Dans le code, le processus parent attend la fin de tous les
processus enfants avec plusieurs appels à la fonction `wait(NULL)`.

Par exemple, après les forks des producteurs et consommateurs, le


processus parent utilise plusieurs appels à `wait(NULL)` pour attendre
que tous les processus enfants se terminent avant de procéder à la
détachement et à la suppression de la mémoire partagée.

L'approche "fork and join" est couramment utilisée dans les


programmes multi-processus pour exploiter la parallélisation et tirer
parti des ressources matérielles disponibles. Chaque processus créé
par `fork()` peut effectuer une tâche spécifique de manière
concurrente, et le processus parent peut attendre la fin de toutes ces
tâches avant de continuer son exécution.

Dans ce contexte, le "fork and join" est utilisé pour créer et


coordonner les producteurs et les consommateurs de manière
synchronisée, garantissant ainsi un comportement correct du problème
producteur-consommateur avec mémoire partagée et sémaphores.
**Conclusion :**

Le code utilise des mécanismes de synchronisation tels que les


sémaphores pour résoudre les problèmes de concurrence et garantir un
accès sûr aux ressources partagées. Il peut être étendu pour gérer un
nombre variable de producteurs et de consommateurs en ajustant les
forks et en modifiant la logique de l'initialisation des identifiants de
classe (`class_id`).

You might also like