Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
2e796b1d83 | |||
9ee8f961b3 | |||
0f0c9a48dc | |||
962ee7180e | |||
70b475b290 | |||
c1eef852db | |||
57fb482c0a | |||
3c4e3c952f | |||
c1a3e1601e | |||
28aa63db4d | |||
29706fe8be | |||
a4e444f43a |
27
System2/RW_problem/Makefile
Normal file
27
System2/RW_problem/Makefile
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
CCOPTIONS=-g
|
||||||
|
CC=gcc $(CCOPTIONS)
|
||||||
|
|
||||||
|
|
||||||
|
all : lecteurs-redacteurs-mutex lecteurs-redacteurs-moniteur
|
||||||
|
|
||||||
|
clean :
|
||||||
|
rm lecteurs-redacteurs-mutex lecteurs-redacteurs-moniteur semaphore-moniteur.o tprintf.o
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lecteurs-redacteurs-mutex : lecteurs-redacteurs-mutex.c tprintf.o
|
||||||
|
$(CC) -o lecteurs-redacteurs-mutex lecteurs-redacteurs-mutex.c tprintf.o -lpthread
|
||||||
|
|
||||||
|
|
||||||
|
lecteurs-redacteurs-moniteur : lecteurs-redacteurs-moniteur.c tprintf.o
|
||||||
|
$(CC) -o lecteurs-redacteurs-moniteur lecteurs-redacteurs-moniteur.c tprintf.o -lpthread
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
semaphore-moniteur.o : semaphore-moniteur.c semaphore-moniteur.h
|
||||||
|
$(CC) -c semaphore-moniteur.c
|
||||||
|
|
||||||
|
tprintf.o : tprintf.c tprintf.h
|
||||||
|
$(CC) -c tprintf.c
|
213
System2/RW_problem/TP3.5.2-README.TXT
Normal file
213
System2/RW_problem/TP3.5.2-README.TXT
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
**********************************
|
||||||
|
TP 5 - Moniteurs et semaphores de comptage en pthread
|
||||||
|
|
||||||
|
Partie 2 : Problème des lecteurs/redacteurs
|
||||||
|
|
||||||
|
Duree: 3h
|
||||||
|
|
||||||
|
**********************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**********************************
|
||||||
|
Resolution du probleme des lecteurs redacteurs avec les pthreads
|
||||||
|
- Partie 2.1: avec des semaphores de comptage uniquement
|
||||||
|
- Partie 2.2: avec des semaphores mutex uniquement
|
||||||
|
- Partie 2.3: avec des moniteurs uniquement
|
||||||
|
**********************************
|
||||||
|
Contenu:
|
||||||
|
|
||||||
|
* lecteurs-redacteurs-mutex.c :
|
||||||
|
Le fichier d'implementation des lecteurs redacteurs pour semaphores mutex uniquement (ou semaphores de comptage) qui contient:
|
||||||
|
lecteur() : fonction principale des threads lecteurs
|
||||||
|
redacteurs () : fonction principale des threads redacteurs
|
||||||
|
main() : fonction principale du processus (initialisation, demarrage/terminaison des threads, finalisation)
|
||||||
|
|
||||||
|
|
||||||
|
* lecteurs-redacteurs-moniteur.c :
|
||||||
|
Le fichier d'implementation des lecteurs redacteurs pour les moniteurs uniquement (mutex et conditions) qui contient:
|
||||||
|
m_prologue_lecteur() et m_epilogue_lecteur(): les points d'entree du moniteur pour les lecteurs
|
||||||
|
m_prologue_redacteur() et m_epilogue_redacteur(): les points d'entree du moniteur pour les redacteurs
|
||||||
|
lecteur() : fonction principale des threads lecteurs
|
||||||
|
redacteurs () : fonction principale des threads redacteurs
|
||||||
|
main() : fonction principale du processus (initialisation, demarrage/terminaison des threads, finalisation)
|
||||||
|
|
||||||
|
|
||||||
|
* semaphore-moniteur.h, semaphore-moniteur.c :
|
||||||
|
Les fichiers d'implementation des semaphores de comptage avec les moniteurs pthreads (à utiliser dans la partie 2.1)
|
||||||
|
type_semaphore ;
|
||||||
|
init_semaphore(); destroy_semaphore();
|
||||||
|
P_semaphore(); V_semaphore();
|
||||||
|
|
||||||
|
|
||||||
|
* tprinf.h, tprinf.c :
|
||||||
|
Les fichiers d'implementation d'un utilitaire tprinf() et tfprintf()
|
||||||
|
printf() prefixe par "seconds:microsecondes:pid: "), a utiliser pour dater tous les messages
|
||||||
|
|
||||||
|
|
||||||
|
* macros-thread.h :
|
||||||
|
un fichier d'utiliaires (macros C) bien pratiques pour simplifier l'utilisation
|
||||||
|
des mutex et des conditions pthread (pour les parties mutex 2.2 et moniteur 2.3))
|
||||||
|
|
||||||
|
|
||||||
|
* makefile :
|
||||||
|
le fichier de construction automatique
|
||||||
|
make all : construit tous les executables
|
||||||
|
make clean : efface tous les fichiers compiles
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*************************************
|
||||||
|
*************************************
|
||||||
|
Sujet de TP :
|
||||||
|
*************************************
|
||||||
|
*************************************
|
||||||
|
|
||||||
|
|
||||||
|
*************************************
|
||||||
|
Partie 2.1 : solution a base de semaphores de comptage
|
||||||
|
fichier: lecteurs-redacteurs-mutex.c
|
||||||
|
*************************************
|
||||||
|
|
||||||
|
1) commencez par analyser en detail le contenu des differents fichiers
|
||||||
|
|
||||||
|
2) compilez le fichier lecteurs-redacteurs-mutex.c avec le makefile et essayer le programme sans synchronisation. Que ce passe-t-il ?
|
||||||
|
|
||||||
|
3) A l'aide de semaphores de comptage , resolvez le probleme des lecteurs redacteurs.
|
||||||
|
Proposez 3 solutions differentes: equite, priorite lecteurs, priorite redacteurs
|
||||||
|
Validez les solutions a l'aide de l'outil JPNS, construisez les reseaux de petri correspondant, et validez-les par simulation.
|
||||||
|
|
||||||
|
4) Implementation des solutions (un fichier different par solution)
|
||||||
|
Implementez les solutions avec le module semaphores de comptage propose dans semaphore-moniteur.h, semaphore-moniteur.c.
|
||||||
|
Encadrez chaque operation P() et V() sur les semaphores d'un messsage tprint() afin de tracer/logger l'instant des operations
|
||||||
|
Modifiez la chaine de lancement des processus lecteurs et redacteurs (macros NBTHREADS et STARTING_CHAIN)
|
||||||
|
utilisez un debogueur/devermineur supportant le parallelisme des threads (gdb, ddd, ...).
|
||||||
|
|
||||||
|
5) Faites la preuve du bon fonctionnement de la solution priorite redacteur:
|
||||||
|
- en analysant les messages encadrant les operation P() et V()
|
||||||
|
- en utilisant les commandes unix ps, top avec les options adaptees aux threads
|
||||||
|
- en dessinant le chronogramme d'utilisation des operations P() et V() des semaphores de comptage pour l'ensemble des threads lecteurs/redacteurs actives.
|
||||||
|
|
||||||
|
|
||||||
|
*************************************
|
||||||
|
Partie 2.2 : solution a base de semaphores mutex
|
||||||
|
fichier: lecteurs-redacteurs-mutex.c
|
||||||
|
*************************************
|
||||||
|
|
||||||
|
3) A l'aide de semaphores mutex pthreads (verrous ou semaphores binaires), resolvez le probleme des lecteurs redacteurs.
|
||||||
|
Proposez 3 solutions differentes: equite, priorite lecteurs, priorite redacteurs
|
||||||
|
Validez les solutions a l'aide de l'outil JPNS, construisez les reseaux de petri correspondant, et validez-les par simulation.
|
||||||
|
|
||||||
|
4) Implementation des solutions (un fichier different par solution)
|
||||||
|
Implementez les solutions avec les mutex pthread (ptread_mutex_* : ptrhread_mutex_t, ptrhread_mutex_init(), ptrhread_mutex_destroy(), ptrhread_mutex_lock(), ptrhread_mutex_unlock() )
|
||||||
|
Vous pouvez aussi utiliser les macros du module macros-thread.h : INIT_MUTEX(), DESTROY_MUTEX(), P_MUTEX(), V__MUTEX()
|
||||||
|
Encadrez chaque operation P() et V() sur les mutex d'un messsage tprint() afin de tracer/logger l'instant des operations
|
||||||
|
Modifiez la chaine de lancement des processus lecteurs et redacteurs (macros NBTHREADS et STARTING_CHAIN)
|
||||||
|
utilisez un debogueur/devermineur supportant le parallelisme des threads (gdb, ddd, ...).
|
||||||
|
|
||||||
|
5) Faites la preuve du bon fonctionnement de la solution priorite redacteur:
|
||||||
|
- en analysant les messages encadrant les operation P() et V()
|
||||||
|
- en utilisant les commandes unix ps, top avec les options adaptees aux threads
|
||||||
|
- en dessinant le chronogramme d'utilisation des operations P() et V() sur les mutex pour l'ensemble des threads lecteurs/redacteurs actives.
|
||||||
|
|
||||||
|
|
||||||
|
*************************************
|
||||||
|
Partie 2.3 : solution a base de moniteurs (mutex et conditions)
|
||||||
|
fichier: lecteurs-redacteurs-moniteur.c
|
||||||
|
*************************************
|
||||||
|
|
||||||
|
1) commencez par analyser en detail le contenu des differents fichiers
|
||||||
|
|
||||||
|
2) compilez le fichier lecteurs-redacteurs-mutex.c avec le makefile et essayer le programme sans synchronisation. Que ce passe-t-il ?
|
||||||
|
|
||||||
|
3) A l'aide des outils moniteur des pthreads (mutex et conditions), resolvez le probleme des lecteurs redacteurs dans lecteurs-redacteurs-moniteur.c.
|
||||||
|
proposez 3 solutions differentes: equite, priorite lecteurs, priorite redacteurs.
|
||||||
|
|
||||||
|
4) Implementation des solutions (un fichier different par solution)
|
||||||
|
Implementez les solutions avec les mutex pthread (ptread_mutex_* : ... ) et les conditions pthread (ptrhread_cond_t, ptrhread_cond_init(), ptrhread_cond_destroy(), ptrhread_cond_wait(), ptrhread_cond_signal() )
|
||||||
|
Vous pouvez aussi utiliser les macros du module macros-thread.h : INIT_MUTEX(), DESTROY_MUTEX(), P_MUTEX(), V__MUTEX(), et INIT_COND(), DESTROY_COND(), WAIT_COND(), SIGNAL__COND()
|
||||||
|
Encadrez chaque operation P(), V(), WAIT(), SIGNAL() sur les mutex et les conditions d'un messsage tprint() afin de tracer/logger l'instant des operations
|
||||||
|
Modifiez la chaine de lancement des processus lecteurs et redacteurs (macros NBTHREADS et STARTING_CHAIN)
|
||||||
|
utilisez un debogueur/devermineur supportant le parallelisme des threads (gdb, ddd, ...).
|
||||||
|
|
||||||
|
5) Faites la preuve du bon fonctionnement de la solution priorite redacteur:
|
||||||
|
- en analysant les messages encadrant les operation P(), V(), WAIT(), SIGNAL()
|
||||||
|
- en utilisant les commandes unix ps, top avec les options adaptees aux threads
|
||||||
|
- en dessinant le chronogramme d'utilisation des operations P(), V(), WAIT(), SIGNAL() sur les mutex et les conditions pour l'ensemble des threads lecteurs/redacteurs actives.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*************************************
|
||||||
|
ANNEXES
|
||||||
|
*************************************
|
||||||
|
1) Déboguer les pthreads avec gdb
|
||||||
|
|
||||||
|
Pour pouvoir controller les threads indépendamment, il suffit d'entrer la séquence de commandes suivante dans gdb:
|
||||||
|
|
||||||
|
# Enable the async interface.
|
||||||
|
set target-async 1
|
||||||
|
# If using the CLI, pagination breaks non-stop.
|
||||||
|
set pagination off
|
||||||
|
# Finally, turn it on!
|
||||||
|
set non-stop on
|
||||||
|
|
||||||
|
Entrer ces commandes dans le fichier ~/.gdbinit pour qu'elles soient prises en compte automatiquement.
|
||||||
|
|
||||||
|
Pour les détails, voir: Non-Stop Mode <https://sourceware.org/gdb/current/onlinedocs/gdb/Non_002dStop-Mode.html>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2) Tutoriel débogueur gdb
|
||||||
|
|
||||||
|
voir : Débuggage avec gdb <https://doc.ubuntu-fr.org/gdb>
|
||||||
|
et Debugging Programs with Multiple Threads <https://sourceware.org/gdb/current/onlinedocs/gdb/Threads.html#Threads>
|
||||||
|
|
||||||
|
|
||||||
|
commande raccourci effet
|
||||||
|
run r lance le programme (s'arrête au prochain point d'arrêt)
|
||||||
|
continue c relance le programme (s'arrête au prochain point d'arrêt)
|
||||||
|
break xx b xx place un point d'arrêt à la ligne ou à la fonction xx
|
||||||
|
info breakpoints info breakpoints liste les points d'arrêts
|
||||||
|
delete d efface les points d'arrêts
|
||||||
|
next n exécute une instruction (ne rentre pas dans les fonctions)
|
||||||
|
step s exécute une instruction (rentre potentiellement dans les fonctions)
|
||||||
|
finish f exécute les instructions jusqu'à la sortie de la fonction
|
||||||
|
until xx u xx exécute les instructions jusqu'à la ligne xx
|
||||||
|
watch var w var surveille la variable var
|
||||||
|
print expr p expr interprète et affiche expr
|
||||||
|
info threads liste les threads en cours (* devant le thread courant)
|
||||||
|
thread thread-id thread id devient le thread courant
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3) Débogueur et IDE
|
||||||
|
|
||||||
|
débogueurs seuls : gdb, DDD, Kdb, ...
|
||||||
|
environnment de developpement (IDE) : eclipse, Kblocks, KDevelop, Code::Blocks, ...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4) Pour deboguer les pthreads en linux dans netbeans. (préférer eclipse)
|
||||||
|
|
||||||
|
Ceci peut être fait dans netbeans 7.0. Pour installer c/c++ dans netbeans, suivre les étapes suivantes:
|
||||||
|
- menu "tools/plugins"
|
||||||
|
- dans settings parametrer le proxy "proxy settings" cache.etu.univ-nantes.fr:3128
|
||||||
|
- dans settings, activez les sources "Certified Plugins, Netbeans Distribution, et Plugin Portal
|
||||||
|
- dans "available plugins" rafraichir le catalogue (update ou refresh), puis installer c/c++
|
||||||
|
|
||||||
|
Il faut aussi mettre à jour netbeans:
|
||||||
|
- dans "update" rafraichir le catalogue (update ou refresh), puis bouton update
|
||||||
|
|
||||||
|
La console gdb est accessible dans menu: "window/debugging/debugger console"
|
||||||
|
|
||||||
|
La fenêtre de contrôle des threads dans : "window/debugging/threads"
|
||||||
|
|
||||||
|
Entrer les commandes de la 1ere partie dans le fichier ~/.gdbinit pour qu'elles soient prises en compte automatiquement.
|
||||||
|
|
||||||
|
|
||||||
|
|
229
System2/RW_problem/lecteurs-redacteurs-moniteur.c
Normal file
229
System2/RW_problem/lecteurs-redacteurs-moniteur.c
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* Problème des Lecteurs rédacteurs
|
||||||
|
* bibliothèque pthread
|
||||||
|
* Solution avec moniteurs (mutex et conditions)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "macros-thread.h"
|
||||||
|
#include "tprintf.h"
|
||||||
|
|
||||||
|
/* Modifier ici la chaine de lancement des threads */
|
||||||
|
#define NBTHREADS 6
|
||||||
|
#define STARTING_CHAIN {"w1","r1", "r2", "r3", "w2", "r4"}
|
||||||
|
|
||||||
|
|
||||||
|
/* Notions Globales */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Définition du moniteur: variables d'état, mutex, conditions */
|
||||||
|
/* ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
int nbLecteurs=0; /* Ressource Critique */
|
||||||
|
int nbRedacteurs=0; /* Ressource Critique */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* declarer mutex et conditions pour le moniteur */
|
||||||
|
|
||||||
|
|
||||||
|
/* Points d'entrée du moniteur proteges par E.M.*/
|
||||||
|
void m_prologue_lecteur(char *);
|
||||||
|
void m_epilogue_lecteur(char *);
|
||||||
|
void m_prologue_redacteur(char *);
|
||||||
|
void m_epilogue_redacteur(char *);
|
||||||
|
|
||||||
|
|
||||||
|
/* Fonctions du moniteur */
|
||||||
|
|
||||||
|
void m_prologue_lecteur(char * nom) {
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Section à mettre en Exclusion Mutuelle */
|
||||||
|
/* par ex:
|
||||||
|
tprintf("producteur %s demande P(mutex)...\n", nom);
|
||||||
|
P_MUTEX(mutex);
|
||||||
|
tprintf("producteur %s obtient P(mutex)...\n", nom);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* code en E.M. sur mutex */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* gerer la synchronisation lecteurs/redacteurs */
|
||||||
|
|
||||||
|
nbLecteurs ++;
|
||||||
|
|
||||||
|
/* fin d'E.M. */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Mettre fin à la section en Exclusion Mutuelle */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void m_epilogue_lecteur(char * nom) {
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Section à mettre en Exclusion Mutuelle */
|
||||||
|
|
||||||
|
/* code en E.M. sur mutex */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* gerer la synchronisation lecteurs/redacteurs */
|
||||||
|
|
||||||
|
nbLecteurs --;
|
||||||
|
|
||||||
|
/* fin d'E.M. */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Mettre fin à la section en Exclusion Mutuelle */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void m_prologue_redacteur(char * nom) {
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Section à mettre en Exclusion Mutuelle */
|
||||||
|
|
||||||
|
/* code en E.M. sur mutex */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* gerer la synchronisation lecteurs/redacteurs */
|
||||||
|
|
||||||
|
nbRedacteurs=1;
|
||||||
|
|
||||||
|
/* fin d'E.M. */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Mettre fin à la section en Exclusion Mutuelle */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void m_epilogue_redacteur(char * nom) {
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Section à mettre en Exclusion Mutuelle */
|
||||||
|
|
||||||
|
/* code en E.M. sur mutex */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* gerer la synchronisation lecteurs/redacteurs */
|
||||||
|
|
||||||
|
nbRedacteurs=0;
|
||||||
|
|
||||||
|
/* fin d'E.M. */
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Mettre fin à la section en Exclusion Mutuelle */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* fin de definition du moniteur */
|
||||||
|
/* ----------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Fonction principales des threads "redacteur" */
|
||||||
|
void * redacteur(void * arg) {
|
||||||
|
char * nom = *(char **)arg;
|
||||||
|
|
||||||
|
tprintf("debut thread redacteur %s\n", nom);
|
||||||
|
|
||||||
|
m_prologue_redacteur(nom);
|
||||||
|
|
||||||
|
tprintf("%s ecrit...\n", nom);
|
||||||
|
sleep(5+rand()%6);
|
||||||
|
|
||||||
|
tprintf("%s etat du tampon partage: nbLecteurs=%i\n", nom, nbLecteurs);
|
||||||
|
tprintf("%s a fini d ecrire...\n", nom);
|
||||||
|
|
||||||
|
m_epilogue_redacteur(nom);
|
||||||
|
|
||||||
|
tprintf("fin thread redacteur %s\n", nom);
|
||||||
|
pthread_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fonction principales des threads "lecteur" */
|
||||||
|
void * lecteur(void * arg) {
|
||||||
|
char * nom = *(char **)arg;
|
||||||
|
|
||||||
|
tprintf("debut thread lecteur %s\n", nom);
|
||||||
|
|
||||||
|
m_prologue_lecteur(nom);
|
||||||
|
|
||||||
|
tprintf("%s lit...\n", nom);
|
||||||
|
sleep(1+rand()%3);
|
||||||
|
tprintf("%s a fini de lire...\n", nom);
|
||||||
|
|
||||||
|
m_epilogue_lecteur(nom);
|
||||||
|
|
||||||
|
tprintf("fin thread lecteur %s\n", nom);
|
||||||
|
pthread_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Affichage de la chaine de lancement des threads */
|
||||||
|
char * chaine_lancement(char * nomsThreads[], char * sep) {
|
||||||
|
static char starting_chain[3*NBTHREADS+1]="";
|
||||||
|
strcat(starting_chain, nomsThreads[0]) ;
|
||||||
|
for ( int i=1; i<NBTHREADS; i++ ) {
|
||||||
|
strcat(starting_chain, sep) ;
|
||||||
|
strcat(starting_chain, nomsThreads[i]) ;
|
||||||
|
}
|
||||||
|
return starting_chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Fonction principales de demarrage et de creation des threads */
|
||||||
|
int main () {
|
||||||
|
|
||||||
|
/* Changer cette chaine de lancement des processus pour tester d'autres configurations */
|
||||||
|
char * nomsThreads[NBTHREADS] = STARTING_CHAIN;
|
||||||
|
pthread_t threads[NBTHREADS];
|
||||||
|
|
||||||
|
void * (* thread_main) (void *);
|
||||||
|
int i, errcode;
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* initialiser les mutex et conditions du moniteur */
|
||||||
|
|
||||||
|
nbLecteurs=0;
|
||||||
|
nbRedacteurs=0;
|
||||||
|
|
||||||
|
/* Affichage de la chaine de lancement des threads */
|
||||||
|
tprintf("Chaine de lancement des threads : %s \n", chaine_lancement(nomsThreads, " ") );
|
||||||
|
|
||||||
|
for ( i=0; i<NBTHREADS; i++ ){
|
||||||
|
if ( nomsThreads[i][0]=='r' ) {
|
||||||
|
thread_main = lecteur;
|
||||||
|
} else if ( nomsThreads[i][0]=='w' ) {
|
||||||
|
thread_main = redacteur;
|
||||||
|
}
|
||||||
|
errcode=pthread_create (&threads[i], NULL, thread_main, &nomsThreads[i]);
|
||||||
|
if ( errcode != 0 ) {
|
||||||
|
fprintf(stderr, "Erreur de creation du thread %s\n", nomsThreads[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<NBTHREADS; i++) {
|
||||||
|
errcode=pthread_join (threads[i], NULL);
|
||||||
|
if (errcode) {
|
||||||
|
fprintf(stderr, "erreur pthread_join pour le thread %s\n", nomsThreads[i]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Detruire les mutex et conditions du moniteur */
|
||||||
|
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
128
System2/RW_problem/lecteurs-redacteurs-mutex.c
Normal file
128
System2/RW_problem/lecteurs-redacteurs-mutex.c
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Problème des Lecteurs rédacteurs
|
||||||
|
* bibliothèque pthread
|
||||||
|
* Solution avec semaphores mutex uniquement
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "macros-thread.h"
|
||||||
|
#include "tprintf.h"
|
||||||
|
|
||||||
|
/* Modifier ici la chaine de lancement des threads */
|
||||||
|
#define NBTHREADS 6
|
||||||
|
#define STARTING_CHAIN {"w1","r1", "r2", "r3", "w2", "r4"}
|
||||||
|
|
||||||
|
/* Notions Globales */
|
||||||
|
|
||||||
|
#define NBTHREADS 6
|
||||||
|
|
||||||
|
int nbLecteurs = 0;
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* declarer les semaphores mutex */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Fonction principales des threads "redacteur" */
|
||||||
|
void * redacteur(void * arg) {
|
||||||
|
char * nom = *(char **)arg;
|
||||||
|
|
||||||
|
tprintf("debut thread redacteur %s\n", nom);
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* gerer la synchronisation lecteurs/redacteurs */
|
||||||
|
|
||||||
|
tprintf("%s ecrit...\n", nom);
|
||||||
|
sleep(5+rand()%6);
|
||||||
|
tprintf("%s : nbLecteurs=%i\n", nom, nbLecteurs);
|
||||||
|
tprintf("%s a fini d ecrire...\n", nom);
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* gerer la synchronisation lecteurs/redacteurs */
|
||||||
|
|
||||||
|
tprintf("fin thread redacteur %s\n", nom);
|
||||||
|
pthread_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fonction principales des threads "lecteur" */
|
||||||
|
void * lecteur(void * arg) {
|
||||||
|
char * nom = *(char **)arg;
|
||||||
|
|
||||||
|
tprintf("debut thread lecteur %s\n", nom);
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* gerer la synchronisation lecteurs/redacteurs */
|
||||||
|
|
||||||
|
tprintf("%s lit...\n", nom);
|
||||||
|
sleep(1+rand()%3);
|
||||||
|
tprintf("%s a fini de lire...\n", nom);
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* gerer la synchronisation lecteurs/redacteurs */
|
||||||
|
|
||||||
|
tprintf("fin thread lecteur %s\n", nom);
|
||||||
|
pthread_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Affichage de la chaine de lancement des threads */
|
||||||
|
char * chaine_lancement(char * nomsThreads[], char * sep) {
|
||||||
|
static char starting_chain[3*NBTHREADS+1]="";
|
||||||
|
strcat(starting_chain, nomsThreads[0]) ;
|
||||||
|
for ( int i=1; i<NBTHREADS; i++ ) {
|
||||||
|
strcat(starting_chain, sep) ;
|
||||||
|
strcat(starting_chain, nomsThreads[i]) ;
|
||||||
|
}
|
||||||
|
return starting_chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Fonction principales de demarrage et de creation des threads */
|
||||||
|
int main () {
|
||||||
|
|
||||||
|
/* Changer cette chaine de lancement des processus pour tester d'autres configurations */
|
||||||
|
char * nomsThreads[NBTHREADS] = STARTING_CHAIN;
|
||||||
|
pthread_t threads[NBTHREADS];
|
||||||
|
void * (* thread_main) (void *);
|
||||||
|
int i, errcode;
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* initialiser les semaphores mutex */
|
||||||
|
|
||||||
|
|
||||||
|
/* Affichage de la chaine de lancement des threads */
|
||||||
|
tprintf("Chaine de lancement des threads : %s \n", chaine_lancement(nomsThreads, " ") );
|
||||||
|
|
||||||
|
/* Creation des threads lecteurs et redacteurs */
|
||||||
|
for ( i=0; i<NBTHREADS; i++ ){
|
||||||
|
if ( nomsThreads[i][0]=='w' ) {
|
||||||
|
thread_main = redacteur;
|
||||||
|
} else if ( nomsThreads[i][0]=='r' ) {
|
||||||
|
thread_main = lecteur;
|
||||||
|
}
|
||||||
|
errcode=pthread_create (&threads[i], NULL, thread_main, &nomsThreads[i]);
|
||||||
|
if ( errcode != 0 ) {
|
||||||
|
fprintf(stderr, "Erreur de creation du thread %s\n", nomsThreads[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attente de terminaison de tous les threads */
|
||||||
|
for (i=0; i<NBTHREADS; i++) {
|
||||||
|
errcode=pthread_join (threads[i], NULL);
|
||||||
|
if (errcode) {
|
||||||
|
fprintf(stderr, "erreur pthread_join pour le thread %s\n", nomsThreads[i]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- A COMPLETER -- */
|
||||||
|
/* Detruire les semaphores mutex */
|
||||||
|
|
||||||
|
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
31
System2/RW_problem/macros-thread.h
Normal file
31
System2/RW_problem/macros-thread.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/* Ensemble de macros bien pratiques pour les moniteurs pthreads */
|
||||||
|
|
||||||
|
#ifndef _MACROS_THREADS_H_
|
||||||
|
#define _MACROS_THREADS_H_
|
||||||
|
|
||||||
|
|
||||||
|
/* Mutex */
|
||||||
|
|
||||||
|
#define INIT_MUTEX(unMutex) if (pthread_mutex_init(&(unMutex), NULL)) { perror("pthread_mutex_init (&(unMutex), NULL)"); pthread_exit(NULL);}
|
||||||
|
|
||||||
|
#define P_MUTEX(unMutex) if (pthread_mutex_lock(&(unMutex))) { perror("pthread_mutex_lock(&(unMutex))"); pthread_exit(NULL);}
|
||||||
|
|
||||||
|
#define V_MUTEX(unMutex) if (pthread_mutex_unlock(&(unMutex))) { perror("pthread_mutex_unlock(&(unMutex))"); pthread_exit(NULL);}
|
||||||
|
|
||||||
|
#define DESTROY_MUTEX(unMutex) if (pthread_mutex_destroy(&(unMutex))) { perror("pthread_mutex_destroy(&(unMutex))"); pthread_exit(NULL);}
|
||||||
|
|
||||||
|
|
||||||
|
/* Conditions */
|
||||||
|
|
||||||
|
#define INIT_COND(uneCondition) if (pthread_cond_init(&(uneCondition), NULL)) { perror("pthread_cond_init(&(uneCondition), NULL)"); pthread_exit(NULL);}
|
||||||
|
|
||||||
|
#define WAIT_COND(uneCondition,unMutex) if (pthread_cond_wait(&(uneCondition), &(unMutex))) { perror("pthread_cond_wait(&(uneCondition), &(unMutex))"); pthread_exit(NULL);}
|
||||||
|
|
||||||
|
#define SIGNAL_COND(uneCondition) if (pthread_cond_signal(&(uneCondition))) { perror("pthread_cond_signal(&(uneCondition))"); pthread_exit(NULL);}
|
||||||
|
|
||||||
|
#define DESTROY_COND(uneCondition) if (pthread_cond_destroy(&(uneCondition))) { perror("pthread_cond_destroy(&(uneCondition))"); pthread_exit(NULL);}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
103
System2/RW_problem/semaphore-moniteur.c
Normal file
103
System2/RW_problem/semaphore-moniteur.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Implementation d'un sémaphore de comptage par moniteurs
|
||||||
|
* bibliothèque pthread
|
||||||
|
* moniteurs = semaphores binaires (mutex) + conditions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "tprintf.h"
|
||||||
|
#include "macros-thread.h"
|
||||||
|
#include "semaphore-moniteur.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Définition du moniteur */
|
||||||
|
/* ---------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/* Points d'entrée */
|
||||||
|
/* Fonctions du moniteur */
|
||||||
|
/* seulement 2 fonctions en exclusion mutuelle : P_semaphore() et V_semaphore() */
|
||||||
|
/* Attention, les autres fonction sne sont pas protegees */
|
||||||
|
|
||||||
|
|
||||||
|
void init_semaphore(type_semaphore * sem, int val){
|
||||||
|
|
||||||
|
/* implementer l'initialisation de tous les champs
|
||||||
|
de l'enregistrement type-semaphore: mutex, attenteFifo, nbAttente, value
|
||||||
|
utiliser INIT_MUTEX, et INIT_COND
|
||||||
|
*/
|
||||||
|
INIT_MUTEX(sem->mutex);
|
||||||
|
INIT_COND(sem->attenteFifo);
|
||||||
|
sem->nbAttente=0;
|
||||||
|
sem->value=val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void P_semaphore(type_semaphore * sem){
|
||||||
|
|
||||||
|
/* implementer l'operateur semaphore P(sem) en exclusion mutuelle
|
||||||
|
modifie les champs de l'enregistrement type-semaphore: nbAttente, value
|
||||||
|
utiliser P_MUTEX, V_MUTEX et WAIT_COND
|
||||||
|
*/
|
||||||
|
P_MUTEX(sem->mutex);
|
||||||
|
sem->value--;
|
||||||
|
if ( sem->value < 0 ) {
|
||||||
|
sem->nbAttente++;
|
||||||
|
WAIT_COND(sem->attenteFifo,sem->mutex);
|
||||||
|
sem->nbAttente--;
|
||||||
|
}
|
||||||
|
V_MUTEX(sem->mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void V_semaphore(type_semaphore * sem){
|
||||||
|
|
||||||
|
/* implementer l'operateur semaphore V(sem) en exclusion mutuelle
|
||||||
|
modifie les champs de l'enregistrement type-semaphore: value
|
||||||
|
utiliser P_MUTEX, V_MUTEX et SIGNAL_COND
|
||||||
|
*/
|
||||||
|
P_MUTEX(sem->mutex);
|
||||||
|
sem->value++;
|
||||||
|
if ( sem->value <= 0 ) {
|
||||||
|
SIGNAL_COND(sem->attenteFifo);
|
||||||
|
}
|
||||||
|
V_MUTEX(sem->mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void destroy_semaphore(type_semaphore * sem){
|
||||||
|
|
||||||
|
/* implementer la destruction du semaphore
|
||||||
|
modifie les champs de l'enregistrement type-semaphore: nbAttente, value
|
||||||
|
*/
|
||||||
|
DESTROY_MUTEX(sem->mutex);
|
||||||
|
DESTROY_COND(sem->attenteFifo);
|
||||||
|
sem->nbAttente=0;
|
||||||
|
sem->value=0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int value_semaphore(type_semaphore * sem){
|
||||||
|
|
||||||
|
/* implementer la lecture non protegee de la valeur du semaphore: champs value */
|
||||||
|
|
||||||
|
return sem->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int estVideFifo_semaphore(type_semaphore * sem){
|
||||||
|
|
||||||
|
/* implementer l'acces au nombre de processus en attente en liste Fifo semaphore: champs nbAttente */
|
||||||
|
|
||||||
|
return sem->nbAttente==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
33
System2/RW_problem/semaphore-moniteur.h
Normal file
33
System2/RW_problem/semaphore-moniteur.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Implementation de semaphore de comptage par moniteur
|
||||||
|
* bibliothèque pthread
|
||||||
|
* Moniteur = semaphores binaires(mutex) + conditions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SEM_
|
||||||
|
#define _SEM_
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/* Notions Globales */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t attenteFifo;
|
||||||
|
int nbAttente;
|
||||||
|
int value;
|
||||||
|
} type_semaphore;
|
||||||
|
|
||||||
|
void init_semaphore(type_semaphore * sem,int val);
|
||||||
|
void P_semaphore(type_semaphore * sem);
|
||||||
|
void V_semaphore(type_semaphore * sem);
|
||||||
|
void destroy_semaphore(type_semaphore * sem);
|
||||||
|
int value_semaphore(type_semaphore * sem);
|
||||||
|
int estVideFifo_semaphore(type_semaphore * sem);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
48
System2/RW_problem/tprintf.c
Normal file
48
System2/RW_problem/tprintf.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* Utilitaire printf estampille : a reutiliser ...
|
||||||
|
print et fprintf prefixes par "seconds:microsecondes:pid: " ou "seconds:microsecondes:pid:tid: "
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "tprintf.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* printf estampille : a reutiliser ... */
|
||||||
|
|
||||||
|
int tprintf(const char * message, ... ) {
|
||||||
|
va_list liste;
|
||||||
|
char chaine [1000];
|
||||||
|
struct timeval t;
|
||||||
|
int pid = getpid();
|
||||||
|
int tid = (int) syscall(SYS_gettid);
|
||||||
|
va_start(liste, message);
|
||||||
|
gettimeofday( &t, NULL);
|
||||||
|
vsprintf(chaine, message, liste);
|
||||||
|
if ( pid == tid )
|
||||||
|
return printf("%ld:%ld:%i: %s", t.tv_sec, t.tv_usec, pid, chaine );
|
||||||
|
else
|
||||||
|
return printf("%ld:%ld:%i:%i %s", t.tv_sec, t.tv_usec, pid, tid, chaine );
|
||||||
|
}
|
||||||
|
|
||||||
|
int tfprintf(FILE * stream, const char * message, ... ) {
|
||||||
|
va_list liste;
|
||||||
|
char chaine [1000];
|
||||||
|
struct timeval t;
|
||||||
|
int pid = getpid();
|
||||||
|
int tid = (int) syscall(SYS_gettid);
|
||||||
|
va_start(liste, message);
|
||||||
|
gettimeofday( &t, NULL);
|
||||||
|
vsprintf(chaine, message, liste);
|
||||||
|
if ( pid == tid )
|
||||||
|
return fprintf(stream, "%ld:%ld:%i: %s", t.tv_sec, t.tv_usec, pid, chaine );
|
||||||
|
else
|
||||||
|
return fprintf(stream, "%ld:%ld:%i:%i %s", t.tv_sec, t.tv_usec, pid, tid, chaine );
|
||||||
|
}
|
||||||
|
|
11
System2/RW_problem/tprintf.h
Normal file
11
System2/RW_problem/tprintf.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* Utilitaire printf estampille : a reutiliser ...
|
||||||
|
print et fprintf prefixes par "seconds:microsecondes:pid: " ou "seconds:microsecondes:pid:tid: "
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* printf estampille : a reutiliser ... */
|
||||||
|
int tprintf( const char *, ... );
|
||||||
|
int tfprintf(FILE * stream, const char * message, ... );
|
||||||
|
|
23
System2/catch_signal/main.c
Normal file
23
System2/catch_signal/main.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void sig_usr(int signo)
|
||||||
|
{
|
||||||
|
if (signo == SIGUSR1)
|
||||||
|
printf("received SIGUSR1\n");
|
||||||
|
else if (signo == SIGUSR2)
|
||||||
|
printf("received SIGUSR2\n");
|
||||||
|
else
|
||||||
|
printf("received signal %d\n", signo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
|
||||||
|
printf("can't catch SIGUSR1\n");
|
||||||
|
if (signal(SIGUSR2, sig_usr) == SIG_ERR)
|
||||||
|
printf("can't catch SIGUSR2\n");
|
||||||
|
for (;;)
|
||||||
|
pause();
|
||||||
|
}
|
BIN
System2/create_ps/a.out
Executable file
BIN
System2/create_ps/a.out
Executable file
Binary file not shown.
32
System2/create_ps/main.c
Normal file
32
System2/create_ps/main.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
pid_t fpid; // fpid表示fork函数返回的值
|
||||||
|
fpid = fork();
|
||||||
|
// create child process
|
||||||
|
if (fpid == -1)
|
||||||
|
{
|
||||||
|
perror("perror in fork!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fpid == 0)
|
||||||
|
{
|
||||||
|
printf("I am the child process, my process id is %d\n", getpid());
|
||||||
|
sleep(1);
|
||||||
|
printf("child process DONE\n");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("I am the parent process, my process id is %d\n", getpid());
|
||||||
|
wait(NULL);
|
||||||
|
printf("parent process DONE\n");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
12
System2/daemonize/Makefile
Normal file
12
System2/daemonize/Makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
CC=gcc
|
||||||
|
|
||||||
|
all: main clean
|
||||||
|
|
||||||
|
main: main.o
|
||||||
|
$(CC) -o main main.o
|
||||||
|
|
||||||
|
main.o: main.c
|
||||||
|
$(CC) -c main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
1
System2/daemonize/coucou.txt
Normal file
1
System2/daemonize/coucou.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
coucou, je suis bien en vie!
|
75
System2/daemonize/main.c
Normal file
75
System2/daemonize/main.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
bool daemonize()
|
||||||
|
{
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if (setsid() < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
umask(0);
|
||||||
|
chdir("/");
|
||||||
|
FILE *fp;
|
||||||
|
fp = fopen("/Users/mdy/Development/langage_C/System2/daemonize/test.txt", "w");
|
||||||
|
close(STDIN_FILENO);
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
dup(fileno(fp));
|
||||||
|
close(STDERR_FILENO);
|
||||||
|
dup(fileno(fp));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handler(int signum)
|
||||||
|
{
|
||||||
|
if (signum == SIGUSR1)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
fp = fopen("/Users/mdy/Development/langage_C/System2/daemonize/coucou.txt", "w");
|
||||||
|
fprintf(fp, "coucou, je suis bien en vie!\n");
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else if (signum == SIGUSR2)
|
||||||
|
{
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("received signal %d\n", signum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
daemonize();
|
||||||
|
if (signal(SIGUSR1, handler) == SIG_ERR)
|
||||||
|
printf("can't catch SIGUSR1\n");
|
||||||
|
if (signal(SIGUSR2, handler) == SIG_ERR)
|
||||||
|
printf("can't catch SIGUSR2\n");
|
||||||
|
for (;;)
|
||||||
|
pause();
|
||||||
|
}
|
21
System2/example_alarm/main.c
Normal file
21
System2/example_alarm/main.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void sig_handler(int signo)
|
||||||
|
{
|
||||||
|
printf("in handler\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
signal(SIGALRM, sig_handler);
|
||||||
|
alarm(5);
|
||||||
|
for (size_t i = 0; i < 30; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("i = %d, In main\n", i);
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
0
System2/myls/main.c
Normal file
0
System2/myls/main.c
Normal file
12
System2/sendToFile/Makefile
Normal file
12
System2/sendToFile/Makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
CC=gcc
|
||||||
|
|
||||||
|
all: main clean
|
||||||
|
|
||||||
|
main: main.o
|
||||||
|
$(CC) -o main main.o
|
||||||
|
|
||||||
|
main.o: main.c
|
||||||
|
$(CC) -c main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
34
System2/sendToFile/main.c
Normal file
34
System2/sendToFile/main.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
void handler(int signum)
|
||||||
|
{
|
||||||
|
if (signum == SIGUSR1)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
fp = fopen("test.txt", "w");
|
||||||
|
fprintf(fp, "coucou, je suis bien en vie!\n");
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else if (signum == SIGUSR2)
|
||||||
|
{
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("received signal %d\n", signum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
if (signal(SIGUSR1, handler) == SIG_ERR)
|
||||||
|
printf("can't catch SIGUSR1\n");
|
||||||
|
if (signal(SIGUSR2, handler) == SIG_ERR)
|
||||||
|
printf("can't catch SIGUSR2\n");
|
||||||
|
for (;;)
|
||||||
|
pause();
|
||||||
|
}
|
1
System2/sendToFile/test.txt
Normal file
1
System2/sendToFile/test.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
coucou, je suis bien en vie!
|
BIN
TP2/tableau/bubbleSort.o
Executable file
BIN
TP2/tableau/bubbleSort.o
Executable file
Binary file not shown.
BIN
TP2/tableau/quickSort.o
Executable file
BIN
TP2/tableau/quickSort.o
Executable file
Binary file not shown.
267
TP3/List/BlockList.c
Normal file
267
TP3/List/BlockList.c
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "BlockList.h"
|
||||||
|
#define BLOCK_SIZE 5
|
||||||
|
|
||||||
|
struct SList
|
||||||
|
{
|
||||||
|
SCell *first;
|
||||||
|
SCell *last;
|
||||||
|
SBlock *block;
|
||||||
|
SCell *recycle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SCell
|
||||||
|
{
|
||||||
|
int data;
|
||||||
|
SCell *next;
|
||||||
|
SCell *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SBlock
|
||||||
|
{
|
||||||
|
SCell tab[BLOCK_SIZE];
|
||||||
|
SBlock *bnext;
|
||||||
|
};
|
||||||
|
|
||||||
|
SList *CreateList()
|
||||||
|
{
|
||||||
|
SList *list;
|
||||||
|
list->block = CreateBlock();
|
||||||
|
list->first = NULL;
|
||||||
|
list->last = NULL;
|
||||||
|
list->recycle = NULL;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
SBlock *CreateBlock()
|
||||||
|
{
|
||||||
|
SBlock *block = (SBlock *)malloc(sizeof(SBlock));
|
||||||
|
block->bnext = NULL;
|
||||||
|
for (int i; i < BLOCK_SIZE; i++)
|
||||||
|
{
|
||||||
|
block->tab[i].data = NULL;
|
||||||
|
block->tab[i].prev = NULL;
|
||||||
|
block->tab[i].next = NULL;
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteList(SList *list)
|
||||||
|
{
|
||||||
|
SCell *cell = GetFirstElement(list);
|
||||||
|
while (cell != NULL)
|
||||||
|
{
|
||||||
|
SCell *next = GetNextElement(cell);
|
||||||
|
DeleteCell(list, cell);
|
||||||
|
cell = next;
|
||||||
|
}
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetCellFromBlock(SList *list)
|
||||||
|
{
|
||||||
|
SCell *pcell;
|
||||||
|
if ((pcell = GetCellFromRecycle(list)))
|
||||||
|
{
|
||||||
|
return pcell;
|
||||||
|
}
|
||||||
|
while (!(pcell = _GetCellFromBlock(list->block)))
|
||||||
|
{
|
||||||
|
AddBlock(list->block);
|
||||||
|
}
|
||||||
|
return pcell;
|
||||||
|
}
|
||||||
|
|
||||||
|
SBlock *AddBlock(SBlock *blist)
|
||||||
|
{
|
||||||
|
SBlock *pblock = CreateBlock();
|
||||||
|
while (blist->bnext != NULL)
|
||||||
|
{
|
||||||
|
blist = blist->bnext;
|
||||||
|
}
|
||||||
|
blist->bnext = pblock;
|
||||||
|
return pblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *_GetCellFromBlock(SBlock *bList)
|
||||||
|
{
|
||||||
|
while (bList != NULL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < BLOCK_SIZE; i++)
|
||||||
|
{
|
||||||
|
if ((bList->tab)[i].data == NULL)
|
||||||
|
{
|
||||||
|
return &(bList->tab)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bList = bList->bnext;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetCellFromRecycle(SList *list)
|
||||||
|
{
|
||||||
|
SCell *pcell = list->recycle;
|
||||||
|
if (pcell != NULL)
|
||||||
|
{
|
||||||
|
list->recycle = pcell->next;
|
||||||
|
}
|
||||||
|
return pcell;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *AddElementBegin(SList *list, int data)
|
||||||
|
{
|
||||||
|
SCell *cell = GetCellFromBlock(list);
|
||||||
|
cell->data = data;
|
||||||
|
cell->next = list->first;
|
||||||
|
cell->prev = NULL;
|
||||||
|
if (list->first != NULL)
|
||||||
|
{
|
||||||
|
list->first->prev = cell;
|
||||||
|
}
|
||||||
|
list->first = cell;
|
||||||
|
if (list->last == NULL)
|
||||||
|
{
|
||||||
|
list->last = cell;
|
||||||
|
}
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *AddElementEnd(SList *list, int data)
|
||||||
|
{
|
||||||
|
SCell *cell = GetCellFromBlock(list);
|
||||||
|
cell->data = data;
|
||||||
|
cell->next = NULL;
|
||||||
|
cell->prev = list->last;
|
||||||
|
if (list->last != NULL)
|
||||||
|
{
|
||||||
|
list->last->next = cell;
|
||||||
|
}
|
||||||
|
list->last = cell;
|
||||||
|
if (list->first == NULL)
|
||||||
|
{
|
||||||
|
list->first = cell;
|
||||||
|
}
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *AddElementAfter(SList *list, SCell *cell, int data)
|
||||||
|
{
|
||||||
|
if (cell == NULL)
|
||||||
|
{
|
||||||
|
return AddElementBegin(list, data);
|
||||||
|
}
|
||||||
|
else if (cell == list->last)
|
||||||
|
{
|
||||||
|
return AddElementEnd(list, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SCell *newCell = GetCellFromBlock(list);
|
||||||
|
newCell->data = data;
|
||||||
|
newCell->next = cell->next;
|
||||||
|
newCell->prev = cell;
|
||||||
|
cell->next->prev = newCell;
|
||||||
|
cell->next = newCell;
|
||||||
|
return newCell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *RecycleCell(SCell *head, SCell *cell)
|
||||||
|
{
|
||||||
|
cell->next = NULL;
|
||||||
|
SCell *recycle = head;
|
||||||
|
if (recycle == NULL)
|
||||||
|
{
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
while (recycle->next != NULL)
|
||||||
|
{
|
||||||
|
recycle = recycle->next;
|
||||||
|
}
|
||||||
|
recycle->next = cell;
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteCell(SList *list, SCell *cell)
|
||||||
|
{
|
||||||
|
if (cell == list->first)
|
||||||
|
{
|
||||||
|
list->first = cell->next;
|
||||||
|
}
|
||||||
|
if (cell == list->last)
|
||||||
|
{
|
||||||
|
list->last = cell->prev;
|
||||||
|
}
|
||||||
|
if (cell->prev != NULL)
|
||||||
|
{
|
||||||
|
cell->prev->next = cell->next;
|
||||||
|
}
|
||||||
|
if (cell->next != NULL)
|
||||||
|
{
|
||||||
|
cell->next->prev = cell->prev;
|
||||||
|
}
|
||||||
|
list->recycle = RecycleCell(list->recycle, cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetFirstElement(SList *list)
|
||||||
|
{
|
||||||
|
return list->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetLastElement(SList *list)
|
||||||
|
{
|
||||||
|
return list->last;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetNextElement(SCell *cell)
|
||||||
|
{
|
||||||
|
return cell->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetPrevElement(SCell *cell)
|
||||||
|
{
|
||||||
|
return cell->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetData(SCell *cell)
|
||||||
|
{
|
||||||
|
return cell->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintBlockList(SList *list)
|
||||||
|
{
|
||||||
|
printf("Block: ");
|
||||||
|
SBlock *pBlock = list->block;
|
||||||
|
while (pBlock != NULL)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < BLOCK_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (pBlock->tab[i].data != NULL)
|
||||||
|
{
|
||||||
|
printf(" [%d] ", pBlock->tab[i].data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" | NULL | ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("-->");
|
||||||
|
pBlock = pBlock->bnext;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintRecycleList(SList *list)
|
||||||
|
{
|
||||||
|
printf("Recycle: ");
|
||||||
|
SCell *pCell = list->recycle;
|
||||||
|
while (pCell != NULL)
|
||||||
|
{
|
||||||
|
printf("[%d] -> ", pCell->data);
|
||||||
|
pCell = pCell->next;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
30
TP3/List/BlockList.h
Normal file
30
TP3/List/BlockList.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef _LISTE_H
|
||||||
|
#define _LISTE_H
|
||||||
|
|
||||||
|
typedef int Data;
|
||||||
|
typedef struct SCell SCell;
|
||||||
|
typedef struct SList SList;
|
||||||
|
typedef struct SBlock SBlock;
|
||||||
|
|
||||||
|
SList *CreateList();
|
||||||
|
SBlock *CreateBlock();
|
||||||
|
void DeleteList(SList *list);
|
||||||
|
SCell *_GetCellFromBlock(SBlock *bList);
|
||||||
|
SBlock *AddBlock(SBlock *blist);
|
||||||
|
SCell *AddElementBegin(SList *list, Data elem);
|
||||||
|
SCell *AddElementEnd(SList *list, Data elem);
|
||||||
|
SCell *AddElementAfter(SList *list, SCell *cell, Data elem);
|
||||||
|
void DeleteCell(SList *list, SCell *cell);
|
||||||
|
void PrintRecycleList(SList *list);
|
||||||
|
SCell *RecycleCell(SCell *head, SCell *cell);
|
||||||
|
SCell *GetCellFromBlock(SList *list);
|
||||||
|
SCell *GetCellFromRecycle(SList *list);
|
||||||
|
|
||||||
|
SCell *GetFirstElement(SList *list);
|
||||||
|
SCell *GetLastElement(SList *list);
|
||||||
|
SCell *GetPrevElement(SCell *cell);
|
||||||
|
SCell *GetNextElement(SCell *cell);
|
||||||
|
Data GetData(SCell *cell);
|
||||||
|
void PrintBlockList(SList *list);
|
||||||
|
|
||||||
|
#endif
|
96
TP3/List/BlockMain.c
Normal file
96
TP3/List/BlockMain.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "BlockList.h"
|
||||||
|
|
||||||
|
void PrintList(SList *list);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
SList *list;
|
||||||
|
SCell *cell1, *cell2;
|
||||||
|
|
||||||
|
list = CreateList();
|
||||||
|
AddElementEnd(list, 1);
|
||||||
|
AddElementEnd(list, 2);
|
||||||
|
AddElementEnd(list, 3);
|
||||||
|
AddElementEnd(list, 4);
|
||||||
|
cell1 = AddElementEnd(list, 5);
|
||||||
|
AddElementEnd(list, 6);
|
||||||
|
AddElementEnd(list, 7);
|
||||||
|
AddElementEnd(list, 8);
|
||||||
|
cell2 = AddElementEnd(list, 9);
|
||||||
|
|
||||||
|
PrintList(list);
|
||||||
|
PrintBlockList(list);
|
||||||
|
PrintRecycleList(list);
|
||||||
|
DeleteCell(list, cell1);
|
||||||
|
PrintList(list);
|
||||||
|
PrintBlockList(list);
|
||||||
|
PrintRecycleList(list);
|
||||||
|
DeleteCell(list, cell2);
|
||||||
|
PrintList(list);
|
||||||
|
PrintBlockList(list);
|
||||||
|
PrintRecycleList(list);
|
||||||
|
|
||||||
|
AddElementEnd(list, 10);
|
||||||
|
PrintList(list);
|
||||||
|
PrintBlockList(list);
|
||||||
|
PrintRecycleList(list);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// printf("Add 5, 3, 1\n");
|
||||||
|
// AddElementEnd(list, 5);
|
||||||
|
// cell = AddElementEnd(list, 3);
|
||||||
|
// AddElementEnd(list, 1);
|
||||||
|
// PrintList(list);
|
||||||
|
// PrintBlockList(list);
|
||||||
|
// printf("\n");
|
||||||
|
|
||||||
|
// printf("Add 6, 8\n");
|
||||||
|
// AddElementEnd(list, 6);
|
||||||
|
// AddElementEnd(list, 8);
|
||||||
|
// PrintList(list);
|
||||||
|
// PrintBlockList(list);
|
||||||
|
// printf("\n");
|
||||||
|
|
||||||
|
// printf("Add 4\n");
|
||||||
|
// AddElementAfter(list, cell, 4);
|
||||||
|
// PrintList(list);
|
||||||
|
// PrintBlockList(list);
|
||||||
|
// printf("\n");
|
||||||
|
|
||||||
|
// printf("Add 2\n");
|
||||||
|
// AddElementAfter(list, GetFirstElement(list), 2);
|
||||||
|
// PrintList(list);
|
||||||
|
// printf("\n");
|
||||||
|
|
||||||
|
// printf("Delete 3\n");
|
||||||
|
// DeleteCell(list, cell);
|
||||||
|
// PrintList(list);
|
||||||
|
// printf("\n");
|
||||||
|
|
||||||
|
// printf("Add 7\n");
|
||||||
|
// AddElementAfter(list, GetPrevElement(GetLastElement(list)), 7);
|
||||||
|
// PrintList(list);
|
||||||
|
// printf("\n");
|
||||||
|
|
||||||
|
// DeleteList(list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintList(SList *list)
|
||||||
|
{
|
||||||
|
printf("List: ");
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
SCell *cell = GetFirstElement(list);
|
||||||
|
while (cell != NULL)
|
||||||
|
{
|
||||||
|
printf("[%d] -> ", GetData(cell));
|
||||||
|
cell = GetNextElement(cell);
|
||||||
|
}
|
||||||
|
printf("NULL\n");
|
||||||
|
}
|
||||||
|
}
|
140
TP3/List/Liste.c
Normal file
140
TP3/List/Liste.c
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "Liste.h"
|
||||||
|
|
||||||
|
struct SList
|
||||||
|
{
|
||||||
|
SCell *first;
|
||||||
|
SCell *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SCell
|
||||||
|
{
|
||||||
|
int data;
|
||||||
|
SCell *next;
|
||||||
|
SCell *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
SList *CreateList()
|
||||||
|
{
|
||||||
|
SList *list = (SList *)malloc(sizeof(SList));
|
||||||
|
list->first = NULL;
|
||||||
|
list->last = NULL;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteList(SList *list)
|
||||||
|
{
|
||||||
|
SCell *cell = GetFirstElement(list);
|
||||||
|
while (cell != NULL)
|
||||||
|
{
|
||||||
|
SCell *next = GetNextElement(cell);
|
||||||
|
DeleteCell(list, cell);
|
||||||
|
cell = next;
|
||||||
|
}
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *AddElementBegin(SList *list, int data)
|
||||||
|
{
|
||||||
|
SCell *cell = (SCell *)malloc(sizeof(SCell));
|
||||||
|
cell->data = data;
|
||||||
|
cell->next = list->first;
|
||||||
|
cell->prev = NULL;
|
||||||
|
if (list->first != NULL)
|
||||||
|
{
|
||||||
|
list->first->prev = cell;
|
||||||
|
}
|
||||||
|
list->first = cell;
|
||||||
|
if (list->last == NULL)
|
||||||
|
{
|
||||||
|
list->last = cell;
|
||||||
|
}
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *AddElementEnd(SList *list, int data)
|
||||||
|
{
|
||||||
|
SCell *cell = (SCell *)malloc(sizeof(SCell));
|
||||||
|
cell->data = data;
|
||||||
|
cell->next = NULL;
|
||||||
|
cell->prev = list->last;
|
||||||
|
if (list->last != NULL)
|
||||||
|
{
|
||||||
|
list->last->next = cell;
|
||||||
|
}
|
||||||
|
list->last = cell;
|
||||||
|
if (list->first == NULL)
|
||||||
|
{
|
||||||
|
list->first = cell;
|
||||||
|
}
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *AddElementAfter(SList *list, SCell *cell, int data)
|
||||||
|
{
|
||||||
|
if (cell == NULL)
|
||||||
|
{
|
||||||
|
return AddElementBegin(list, data);
|
||||||
|
}
|
||||||
|
else if (cell == list->last)
|
||||||
|
{
|
||||||
|
return AddElementEnd(list, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SCell *newCell = (SCell *)malloc(sizeof(SCell));
|
||||||
|
newCell->data = data;
|
||||||
|
newCell->next = cell->next;
|
||||||
|
newCell->prev = cell;
|
||||||
|
cell->next->prev = newCell;
|
||||||
|
cell->next = newCell;
|
||||||
|
return newCell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteCell(SList *list, SCell *cell)
|
||||||
|
{
|
||||||
|
if (cell == list->first)
|
||||||
|
{
|
||||||
|
list->first = cell->next;
|
||||||
|
}
|
||||||
|
if (cell == list->last)
|
||||||
|
{
|
||||||
|
list->last = cell->prev;
|
||||||
|
}
|
||||||
|
if (cell->prev != NULL)
|
||||||
|
{
|
||||||
|
cell->prev->next = cell->next;
|
||||||
|
}
|
||||||
|
if (cell->next != NULL)
|
||||||
|
{
|
||||||
|
cell->next->prev = cell->prev;
|
||||||
|
}
|
||||||
|
free(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetFirstElement(SList *list)
|
||||||
|
{
|
||||||
|
return list->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetLastElement(SList *list)
|
||||||
|
{
|
||||||
|
return list->last;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetNextElement(SCell *cell)
|
||||||
|
{
|
||||||
|
return cell->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCell *GetPrevElement(SCell *cell)
|
||||||
|
{
|
||||||
|
return cell->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetData(SCell *cell)
|
||||||
|
{
|
||||||
|
return cell->data;
|
||||||
|
}
|
22
TP3/List/Liste.h
Normal file
22
TP3/List/Liste.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _LISTE_H
|
||||||
|
#define _LISTE_H
|
||||||
|
|
||||||
|
typedef int Data;
|
||||||
|
typedef struct SCell SCell;
|
||||||
|
typedef struct SList SList;
|
||||||
|
|
||||||
|
SList *CreateList();
|
||||||
|
void DeleteList(SList *list);
|
||||||
|
|
||||||
|
SCell *AddElementBegin(SList *list, Data elem);
|
||||||
|
SCell *AddElementEnd(SList *list, Data elem);
|
||||||
|
SCell *AddElementAfter(SList *list, SCell *cell, Data elem);
|
||||||
|
void DeleteCell(SList *list, SCell *cell);
|
||||||
|
|
||||||
|
SCell *GetFirstElement(SList *list);
|
||||||
|
SCell *GetLastElement(SList *list);
|
||||||
|
SCell *GetPrevElement(SCell *cell);
|
||||||
|
SCell *GetNextElement(SCell *cell);
|
||||||
|
Data GetData(SCell *cell);
|
||||||
|
|
||||||
|
#endif
|
BIN
TP3/List/a.out
Executable file
BIN
TP3/List/a.out
Executable file
Binary file not shown.
63
TP3/List/main.c
Normal file
63
TP3/List/main.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "Liste.h"
|
||||||
|
|
||||||
|
void PrintList(SList *list);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
SList *list;
|
||||||
|
SCell *cell;
|
||||||
|
|
||||||
|
list = CreateList();
|
||||||
|
printf("Add 5, 3, 1\n");
|
||||||
|
AddElementBegin(list, 5);
|
||||||
|
cell = AddElementBegin(list, 3);
|
||||||
|
AddElementBegin(list, 1);
|
||||||
|
PrintList(list);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Add 6, 8\n");
|
||||||
|
AddElementEnd(list, 6);
|
||||||
|
AddElementEnd(list, 8);
|
||||||
|
PrintList(list);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Add 4\n");
|
||||||
|
AddElementAfter(list, cell, 4);
|
||||||
|
PrintList(list);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Add 2\n");
|
||||||
|
AddElementAfter(list, GetFirstElement(list), 2);
|
||||||
|
PrintList(list);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Delete 3\n");
|
||||||
|
DeleteCell(list, cell);
|
||||||
|
PrintList(list);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Add 7\n");
|
||||||
|
AddElementAfter(list, GetPrevElement(GetLastElement(list)), 7);
|
||||||
|
PrintList(list);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
DeleteList(list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintList(SList *list)
|
||||||
|
{
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
SCell *cell = GetFirstElement(list);
|
||||||
|
while (cell != NULL)
|
||||||
|
{
|
||||||
|
printf("[%d] -> ", GetData(cell));
|
||||||
|
cell = GetNextElement(cell);
|
||||||
|
}
|
||||||
|
printf("NULL\n");
|
||||||
|
}
|
||||||
|
}
|
9
examen/T1/Makefile
Normal file
9
examen/T1/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
CC = gcc
|
||||||
|
|
||||||
|
all: main
|
||||||
|
|
||||||
|
main:
|
||||||
|
$(CC) *.c *.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm a.out
|
52
examen/T1/StatistiqueFichier.c
Normal file
52
examen/T1/StatistiqueFichier.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "StatistiqueFichier.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
ASCII_table init_table()
|
||||||
|
{
|
||||||
|
ASCII_table table;
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
table.ASCII[i] = 0;
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_ASCII_table(ASCII_table *table)
|
||||||
|
{
|
||||||
|
for (int i = 32; i <= 126; i++)
|
||||||
|
{
|
||||||
|
printf("%d ", table->ASCII[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_StatistiqueResultats(ASCII_table *table)
|
||||||
|
{
|
||||||
|
for (int i = 32; i <= 126; i++)
|
||||||
|
{
|
||||||
|
if (table->ASCII[i])
|
||||||
|
{
|
||||||
|
printf("%c: %d\n", i, table->ASCII[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASCII_table *StatistiqueFichier(char *nomFichier, ASCII_table *table)
|
||||||
|
{
|
||||||
|
FILE *pFile;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (pFile = fopen(nomFichier, "rt"))
|
||||||
|
{
|
||||||
|
for (c = fgetc(pFile); !feof(pFile); c = fgetc(pFile))
|
||||||
|
{
|
||||||
|
table->ASCII[(int)c]++;
|
||||||
|
}
|
||||||
|
fclose(pFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("error");
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
9
examen/T1/StatistiqueFichier.h
Normal file
9
examen/T1/StatistiqueFichier.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
typedef struct ASCII_table
|
||||||
|
{
|
||||||
|
int ASCII[256];
|
||||||
|
} ASCII_table;
|
||||||
|
|
||||||
|
ASCII_table init_table();
|
||||||
|
ASCII_table *StatistiqueFichier(char *nomFichier, ASCII_table *table);
|
||||||
|
void print_ASCII_table(ASCII_table *table);
|
||||||
|
void print_StatistiqueResultats(ASCII_table *table);
|
8
examen/T1/fichier.txt
Normal file
8
examen/T1/fichier.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
abcdefg
|
||||||
|
abcdefg
|
||||||
|
abcdefg
|
||||||
|
abcdefg
|
||||||
|
,/df,glsd,lrekg
|
||||||
|
}{}:":L:
|
||||||
|
sdkljflskjdflkajlk. fdjsakljflwa
|
||||||
|
jgriej. giojgrekrjkdskjfklwjk
|
11
examen/T1/main.c
Normal file
11
examen/T1/main.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "StatistiqueFichier.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
ASCII_table table;
|
||||||
|
table = init_table();
|
||||||
|
StatistiqueFichier("fichier.txt", &table);
|
||||||
|
print_StatistiqueResultats(&table);
|
||||||
|
return 0;
|
||||||
|
}
|
9
examen/T2/Makefile
Normal file
9
examen/T2/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
CC = gcc
|
||||||
|
|
||||||
|
all: main
|
||||||
|
|
||||||
|
main:
|
||||||
|
$(CC) *.c *.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm a.out
|
67
examen/T2/arbres_binaires.c
Normal file
67
examen/T2/arbres_binaires.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include "arbres_binaires.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
SNoeud CreerFeuille(float valeur, char lettre)
|
||||||
|
{
|
||||||
|
SNoeud feuille;
|
||||||
|
feuille.valeur = valeur;
|
||||||
|
feuille.est_feuille = true;
|
||||||
|
feuille.lettre = lettre;
|
||||||
|
return feuille;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNoeud_Array *CreerNoeudArray(valeur_lettre *t, int taille)
|
||||||
|
{
|
||||||
|
SNoeud_Array *tableau = malloc(sizeof(SNoeud_Array));
|
||||||
|
tableau->noeud = malloc(sizeof(SNoeud) * taille);
|
||||||
|
tableau->taille = taille;
|
||||||
|
for (int i = 0; i < taille; i++)
|
||||||
|
{
|
||||||
|
tableau->noeud[i] = CreerFeuille(t[i].valeur, t[i].lettre);
|
||||||
|
}
|
||||||
|
return tableau;
|
||||||
|
}
|
||||||
|
|
||||||
|
deux_Noeuds find2min(SNoeud_Array *tableau)
|
||||||
|
{
|
||||||
|
deux_Noeuds min;
|
||||||
|
min.gauche = NULL;
|
||||||
|
min.droite = NULL;
|
||||||
|
int min1 = 0;
|
||||||
|
int min2 = 0;
|
||||||
|
for (int i = 0; i < tableau->taille; i++)
|
||||||
|
{
|
||||||
|
if (tableau->noeud[i].valeur < min1)
|
||||||
|
{
|
||||||
|
min2 = min1;
|
||||||
|
min1 = tableau->noeud[i].valeur;
|
||||||
|
min.droite = min.gauche;
|
||||||
|
min.gauche = &tableau->noeud[i];
|
||||||
|
}
|
||||||
|
else if (tableau->noeud[i].valeur < min2)
|
||||||
|
{
|
||||||
|
min2 = tableau->noeud[i].valeur;
|
||||||
|
min.droite = &tableau->noeud[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNoeud AssocierNoeud(SNoeud gauche, SNoeud droite)
|
||||||
|
{
|
||||||
|
SNoeud noeud;
|
||||||
|
noeud.valeur = gauche.valeur + droite.valeur;
|
||||||
|
noeud.est_feuille = false;
|
||||||
|
noeud.gauche = &gauche;
|
||||||
|
noeud.droite = &droite;
|
||||||
|
return noeud;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNoeud EtapeGlouton(SNoeud_Array *tableau)
|
||||||
|
{
|
||||||
|
deux_Noeuds min = find2min(tableau);
|
||||||
|
SNoeud noeud = AssocierNoeud(*min.gauche, *min.droite);
|
||||||
|
free(min.gauche);
|
||||||
|
free(min.droite);
|
||||||
|
return noeud;
|
||||||
|
}
|
34
examen/T2/arbres_binaires.h
Normal file
34
examen/T2/arbres_binaires.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct SNoeud
|
||||||
|
{
|
||||||
|
float valeur;
|
||||||
|
bool est_feuille;
|
||||||
|
char lettre;
|
||||||
|
struct SNoeud *gauche;
|
||||||
|
struct SNoeud *droite;
|
||||||
|
} SNoeud;
|
||||||
|
|
||||||
|
typedef struct SNoeud_Array
|
||||||
|
{
|
||||||
|
SNoeud *noeud;
|
||||||
|
int taille;
|
||||||
|
} SNoeud_Array;
|
||||||
|
|
||||||
|
typedef struct deux_Noeuds
|
||||||
|
{
|
||||||
|
SNoeud *gauche;
|
||||||
|
SNoeud *droite;
|
||||||
|
} deux_Noeuds;
|
||||||
|
|
||||||
|
typedef struct valeur_lettre
|
||||||
|
{
|
||||||
|
float valeur;
|
||||||
|
char lettre;
|
||||||
|
} valeur_lettre;
|
||||||
|
|
||||||
|
SNoeud_Array *CreerNoeudArray(valeur_lettre* t, int taille);
|
||||||
|
deux_Noeuds find2min(SNoeud_Array *tableau);
|
||||||
|
SNoeud EtapeGlouton(SNoeud_Array *tableau);
|
||||||
|
SNoeud CreerFeuille(float valeur, char lettre);
|
||||||
|
SNoeud AssocierNoeud(SNoeud gauche, SNoeud droite);
|
8
examen/T2/main.c
Normal file
8
examen/T2/main.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "arbres_binaires.h"
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
valeur_lettre vl[6] = {{0.05, 'F'}, {0.1, 'A'}, {0.1, 'B'}, {0.15, 'D'}, {0.25, 'C'}, {0.35, 'E'}};
|
||||||
|
SNoeud_Array *arr = CreerNoeudArray(vl, 6);
|
||||||
|
return 0;
|
||||||
|
}
|
7
langage_C.code-workspace
Normal file
7
langage_C.code-workspace
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user