Importation du code depuis GitHub
This commit is contained in:
commit
05476b94ad
13 changed files with 1080 additions and 0 deletions
10
README.md
Normal file
10
README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Cours de programmation système & multi-threading (I4IRTR11)
|
||||
Partage de mes TD et TP de programmation système & multi-threading effectués lors de mon S6 à l'INSA de Toulouse.
|
||||
|
||||
## Liste des TD validés à présent :
|
||||
* TD1
|
||||
* TD2
|
||||
* TD3
|
||||
* TD4
|
||||
* TD5
|
||||
* TD6 - mais on peut mieux faire
|
||||
33
TD/TD1/main.c
Normal file
33
TD/TD1/main.c
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
void * fn_thread (void * p_int) {
|
||||
for (int i = 0; i < *(int *) p_int; ++i) {
|
||||
printf("et mon courroux\n");
|
||||
sleep(1);
|
||||
}
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
int main () {
|
||||
int M = 0;
|
||||
int N = 0;
|
||||
pthread_t p1;
|
||||
|
||||
printf("Saisir M puis N : \n");
|
||||
scanf ("%d", &M);
|
||||
scanf ("%d", &N);
|
||||
printf("Ok ! \n");
|
||||
|
||||
pthread_create (& p1, NULL, fn_thread, (void *) &N);
|
||||
for (int i = 0; i < M; ++i) {
|
||||
printf("Coucou\n");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
pthread_join(p1, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
TD/TD2/main.c
Normal file
41
TD/TD2/main.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
double * px = NULL;
|
||||
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void * fn_thread (void * p_int) {
|
||||
for (int i = 0; i < *(int *) p_int; ++i) {
|
||||
pthread_mutex_lock(& mutex);
|
||||
printf("%f\n", *px);
|
||||
pthread_mutex_unlock(& mutex);
|
||||
}
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
int main () {
|
||||
int max = 0;
|
||||
pthread_t p1;
|
||||
|
||||
printf("Saisir max : \n");
|
||||
scanf ("%d", &max);
|
||||
printf("Ok ! \n");
|
||||
|
||||
double x = 1.0;
|
||||
px = &x;
|
||||
pthread_create (& p1, NULL, fn_thread, (void *) &max);
|
||||
|
||||
for (int i = 0; i < max; ++i) {
|
||||
pthread_mutex_lock(& mutex);
|
||||
px = NULL;
|
||||
printf("i : %d\n", i);
|
||||
px = &x;
|
||||
pthread_mutex_unlock(& mutex);
|
||||
}
|
||||
|
||||
pthread_join(p1, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
68
TD/TD3/main.c
Normal file
68
TD/TD3/main.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Ressources disponible
|
||||
int M = 4;
|
||||
|
||||
// Mutex
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
void prendre_ressource(int rsc){
|
||||
if (pthread_mutex_lock(&mutex))
|
||||
exit(-1);
|
||||
|
||||
while (rsc > M)
|
||||
pthread_cond_wait(&cond, &mutex);
|
||||
|
||||
if (M - rsc >= 0)
|
||||
M -= rsc;
|
||||
else
|
||||
exit(1);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void liberer_ressource(int rsc){
|
||||
if (pthread_mutex_lock(&mutex))
|
||||
exit(-1);
|
||||
|
||||
M += rsc;
|
||||
|
||||
pthread_cond_broadcast(&cond);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
|
||||
void * fn_thread (void * p_int) {
|
||||
int rsc = *(int *) p_int;
|
||||
printf("Thread en attente pour %d ressource(s)...\n", rsc);
|
||||
prendre_ressource(rsc);
|
||||
printf("Thread a pris %d ressource(s)...\n", rsc);
|
||||
sleep(rsc);
|
||||
printf("%d ressource(s) utilisée(s) et rendue(s)...\n", rsc);
|
||||
liberer_ressource(rsc);
|
||||
printf("Thread (à %d rsc) fini...\n", rsc);
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
int main () {
|
||||
pthread_t p1;
|
||||
pthread_t p2;
|
||||
pthread_t p3;
|
||||
int rsc1 = 3;
|
||||
int rsc2 = 2;
|
||||
int rsc3 = 1;
|
||||
|
||||
pthread_create (& p1, NULL, fn_thread, (void *) &rsc1);
|
||||
pthread_create (& p2, NULL, fn_thread, (void *) &rsc2);
|
||||
pthread_create (& p3, NULL, fn_thread, (void *) &rsc3);
|
||||
|
||||
pthread_join(p1, NULL);
|
||||
pthread_join(p2, NULL);
|
||||
pthread_join(p3, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
50
TD/TD4/main.c
Normal file
50
TD/TD4/main.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Ressources disponible
|
||||
int N = 3;
|
||||
|
||||
// Once
|
||||
pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
pthread_key_t key;
|
||||
|
||||
int incrementation() {
|
||||
int *s_int;
|
||||
s_int = (int*)pthread_getspecific(key);
|
||||
return ++(*s_int);
|
||||
}
|
||||
|
||||
void fonction_init() {
|
||||
printf("Initialisation...\n");
|
||||
pthread_key_create(&key, NULL);
|
||||
}
|
||||
|
||||
void * fn_thread (void * n) {
|
||||
pthread_once(&once, fonction_init);
|
||||
|
||||
int* s_int;
|
||||
s_int = malloc(sizeof(int));
|
||||
*s_int = pthread_self();
|
||||
pthread_setspecific(key, (void *)s_int);
|
||||
|
||||
for (int i = 0; i < N; ++i){
|
||||
printf("Boucle : %d\n", incrementation());
|
||||
}
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
int main () {
|
||||
pthread_t p1;
|
||||
pthread_t p2;
|
||||
|
||||
pthread_create (& p1, NULL, fn_thread, NULL);
|
||||
pthread_create (& p2, NULL, fn_thread, NULL);
|
||||
fn_thread(NULL);
|
||||
|
||||
pthread_join(p1, NULL);
|
||||
pthread_join(p2, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
47
TD/TD5/main.c
Normal file
47
TD/TD5/main.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define max 6
|
||||
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
void unlock(){
|
||||
pthread_mutex_unlock(& mutex);
|
||||
}
|
||||
|
||||
|
||||
void * fn_thread (void * n) {
|
||||
pthread_mutex_lock(& mutex);
|
||||
printf("[THREAD] J'ai le mutex.\n");
|
||||
|
||||
for (int i = 0; i < max; ++i){
|
||||
printf("[THREAD] tid: %ld\n", pthread_self());
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(& mutex);
|
||||
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
|
||||
int main () {
|
||||
pthread_t p1;
|
||||
|
||||
for (int i = 0; i < 2; ++i){
|
||||
pthread_create (& p1, NULL, fn_thread, NULL);
|
||||
pthread_cleanup_push( &unlock, NULL );
|
||||
|
||||
for (int i = 0; i < max/2; ++i){
|
||||
printf("[MAIN] pid: %d\n", getpid());
|
||||
sleep(1);
|
||||
}
|
||||
pthread_cancel(p1);
|
||||
pthread_cleanup_pop(1);
|
||||
sleep(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
66
TD/TD5/sig.c
Normal file
66
TD/TD5/sig.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define max 6
|
||||
|
||||
void handler_sigusr1(int sig) {
|
||||
printf("PID %d a reçu un SIGUSR1 : %d\n", getpid(), sig);
|
||||
}
|
||||
|
||||
void handler_sigusr2(int sig) {
|
||||
printf("PID %d a reçu un SIGUSR2 : %d\n", getpid(), sig);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void * fn_thread (void * n) {
|
||||
|
||||
// Masque tous les signaux sauf SIGUSR1
|
||||
sigset_t ens_signal;
|
||||
sigfillset(&ens_signal);
|
||||
sigdelset(&ens_signal,SIGUSR1);
|
||||
sigprocmask(SIG_SETMASK, &ens_signal,NULL);
|
||||
|
||||
while (1){
|
||||
printf("THREAD up and running.\n");
|
||||
sleep(1);
|
||||
}
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
|
||||
int main () {
|
||||
printf("Entry.\n");
|
||||
|
||||
// Configuration des signaux
|
||||
struct sigaction action;
|
||||
struct sigaction action2;
|
||||
action.sa_handler = handler_sigusr1;
|
||||
action2.sa_handler = handler_sigusr2;
|
||||
|
||||
if (sigaction(SIGUSR1, &action, NULL) || sigaction(SIGUSR2, &action2, NULL)) {
|
||||
printf("Erreur handler (SIGUSR1).\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Création du thread
|
||||
pthread_t p1;
|
||||
pthread_create (& p1, NULL, fn_thread, NULL);
|
||||
|
||||
// Masque tous les signaux sauf SIGUSR2
|
||||
sigset_t ens_signal;
|
||||
sigfillset(&ens_signal);
|
||||
sigdelset(&ens_signal,SIGUSR2);
|
||||
sigprocmask(SIG_SETMASK, &ens_signal,NULL);
|
||||
|
||||
while (1){
|
||||
printf("MAIN up and running (pid: %d).\n", getpid());
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
77
TD/TD6/main.c
Normal file
77
TD/TD6/main.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define NB_THREAD 4
|
||||
#define F 10000000
|
||||
|
||||
// Nombre de point à l'intérieur du cercle
|
||||
int retvals[NB_THREAD];
|
||||
int t_num = 0;
|
||||
|
||||
|
||||
/// Fonction de calcul en thread
|
||||
void * fn_thread (void * p_int) {
|
||||
// Le thread récupère un numéro
|
||||
int num = t_num;
|
||||
++t_num;
|
||||
long double x, y;
|
||||
int fn = F/NB_THREAD;
|
||||
int in = 0;
|
||||
|
||||
for (int i = 0; i < fn; ++i) {
|
||||
// On tire aléatoirement x et y entre -1 et 1
|
||||
x = (long double)rand()/(long double)(RAND_MAX);
|
||||
y = (long double)rand()/(long double)(RAND_MAX);
|
||||
|
||||
if ((x*x) + (y*y) <= 1.0)
|
||||
++in;
|
||||
}
|
||||
retvals[num] = in;
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
int main () {
|
||||
pthread_t threads[NB_THREAD];
|
||||
|
||||
// Graine aléatoire avec le temps
|
||||
srand(time(NULL));
|
||||
|
||||
// Outils pour le chronometre
|
||||
struct timeval begin, end;
|
||||
gettimeofday(&begin, NULL);
|
||||
|
||||
// Lancement des threads
|
||||
for (int j = 0; j < NB_THREAD; ++j) {
|
||||
if (pthread_create(&threads[j], NULL, fn_thread, NULL) != 0) {
|
||||
fprintf(stderr, "Cannot create thread # %d\n", j);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Joining threads
|
||||
for (int i = 0; i < NB_THREAD; ++i) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
//Summing all "in" points
|
||||
int in = 0;
|
||||
for (int i = 0; i < NB_THREAD; ++i) {
|
||||
in += retvals[i];
|
||||
}
|
||||
|
||||
// Calculing pi
|
||||
long double pi = ((long double) in * 4.0) / (long double) F;
|
||||
|
||||
// Stopping timer
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
//printf("Ratio inside / outside : %d/%d\n", in, F - in);
|
||||
printf("Valeur calculée de pi : %Lf\n", pi);
|
||||
printf("Nombre de thread : %d\n", NB_THREAD);
|
||||
printf("Nombre de point : %d\n", F);
|
||||
printf("Time: %ld microseconds\n", ((end.tv_sec - begin.tv_sec)*1000000L + end.tv_usec) - begin.tv_usec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
98
TP/TP1/main.c
Normal file
98
TP/TP1/main.c
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define NB_ITR 100000
|
||||
|
||||
void handler_sigusr1(int sig) {
|
||||
printf("PID %d a reçu un SIGUSR1 : %d\n", getpid(), sig);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void handler_sigchld(int sig) {
|
||||
printf("PID %d a reçu un SIGCHLD : %d\n", getpid(), sig);
|
||||
printf("Le fils est mort...\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Variables fork
|
||||
int pid = 0;
|
||||
|
||||
// Variables gestion des signaux
|
||||
struct sigaction action;
|
||||
struct sigaction action2;
|
||||
action.sa_handler = handler_sigusr1;
|
||||
action2.sa_handler = handler_sigchld;
|
||||
|
||||
// Variables tubes
|
||||
int p1[2];
|
||||
int p2[2];
|
||||
int tsfr = 0;
|
||||
int tsfr2 = 0;
|
||||
|
||||
// Outils pour le chronometre
|
||||
struct timeval begin, end;
|
||||
|
||||
// Initialisation des signaux
|
||||
if (sigaction(SIGUSR1, &action, NULL)) {
|
||||
printf("Erreur handler (SIGUSR1).\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (sigaction(SIGCHLD, &action2, NULL)) {
|
||||
printf("Erreur handler (SIGCHLD).\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Initialisation des tubes
|
||||
if (pipe(p1) || pipe(p2)) {
|
||||
printf("Erreur pipe.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Fork
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
printf("Erreur fork.\n");
|
||||
exit(-1);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
printf("Le fils a correctement démarré (PID %d)\n", getpid());
|
||||
|
||||
// On lit, on incrémente et on renvoie
|
||||
while (1) {
|
||||
read(p1[0], &tsfr2, sizeof(tsfr2));
|
||||
++tsfr2;
|
||||
write(p2[1], &tsfr2, sizeof(tsfr2));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Le père est ok (PID %d), le PID du fils est %d\n", getpid(), pid);
|
||||
|
||||
// Comme le fils, mais on chronometre
|
||||
int nb_boucle = 0;
|
||||
gettimeofday(&begin, NULL);
|
||||
while (nb_boucle < NB_ITR) {
|
||||
++tsfr;
|
||||
write(p1[1], &tsfr, sizeof(tsfr));
|
||||
read(p2[0], &tsfr, sizeof(tsfr));
|
||||
nb_boucle++;
|
||||
}
|
||||
gettimeofday(&end, NULL);
|
||||
kill(pid, SIGUSR1);
|
||||
|
||||
// On calcul le débit
|
||||
int delta = ((end.tv_sec - begin.tv_sec)*1000000L + end.tv_usec) - begin.tv_usec;
|
||||
int debit = (nb_boucle*2*sizeof(tsfr2)*8)/(delta); // (delta est déjà en us)
|
||||
|
||||
printf("Débit calculé : %d Mb/s\n", debit);
|
||||
printf("[DEBUG] delta : %d us, tsfr : %d\n", delta, tsfr);
|
||||
|
||||
return debit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
110
TP/TP1/tube_nomme.c
Normal file
110
TP/TP1/tube_nomme.c
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define NB_ITR 1000
|
||||
|
||||
void utilisation() {
|
||||
printf("Usage : ./a.out [c] [s]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void server() {
|
||||
printf("Server mode (ping only)...\n");
|
||||
|
||||
// Variables tube nommé
|
||||
int d_lect_1, d_ecr_1;
|
||||
int d_lect_2, d_ecr_2;
|
||||
|
||||
printf("Création des tubes...");
|
||||
if (mkfifo("/tmp/tube1", S_IRUSR | S_IWUSR | S_IRGRP)
|
||||
|| mkfifo("/tmp/tube2", S_IRUSR | S_IWUSR | S_IRGRP)) {
|
||||
printf("Erreur tube.\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf("OK\n");
|
||||
|
||||
printf("Ouverture des tubes...");
|
||||
if (!(d_lect_1 = open("/tmp/tube1", O_RDONLY))){
|
||||
printf("Erreur ouverture tube (READ).\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf("OK1...");
|
||||
|
||||
if (!(d_ecr_2 = open("/tmp/tube2", O_WRONLY))){
|
||||
printf("Erreur ouverture tube (WRITE).\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf("OK2\n");
|
||||
|
||||
// On lit, on incrémente et on renvoie
|
||||
int tsfr = 0;
|
||||
while (1) {
|
||||
read(d_lect_1, &tsfr, sizeof(tsfr));
|
||||
++tsfr;
|
||||
write(d_ecr_2, &tsfr, sizeof(tsfr));
|
||||
}
|
||||
}
|
||||
|
||||
void client() {
|
||||
printf("Client mode...\n");
|
||||
|
||||
// Variables tube nommé
|
||||
int d_lect_1, d_ecr_1;
|
||||
int d_lect_2, d_ecr_2;
|
||||
|
||||
printf("Ouverture des tubes...\n");
|
||||
if (!(d_ecr_1 = open("/tmp/tube1", O_WRONLY))){
|
||||
printf("Erreur ouverture tube (WRITE).\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!(d_lect_2 = open("/tmp/tube2", O_RDONLY))){
|
||||
printf("Erreur ouverture tube (READ).\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf("Tubes ouverts.\n");
|
||||
|
||||
// Outils pour le chronometre
|
||||
struct timeval begin, end;
|
||||
|
||||
// Ping pong
|
||||
int tsfr = 0;
|
||||
int nb_boucle = 0;
|
||||
printf("Lancement du chronometre.\n");
|
||||
gettimeofday(&begin, NULL);
|
||||
while (nb_boucle < NB_ITR) {
|
||||
++tsfr;
|
||||
write(d_ecr_1, &tsfr, sizeof(tsfr));
|
||||
read(d_lect_2, &tsfr, sizeof(tsfr));
|
||||
nb_boucle++;
|
||||
}
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
// On calcul le débit
|
||||
int delta =
|
||||
((end.tv_sec - begin.tv_sec) * 1000000L + end.tv_usec) - begin.tv_usec;
|
||||
int debit =
|
||||
(nb_boucle * 2 * sizeof(tsfr) * 8) / (delta); // (delta est déjà en us)
|
||||
|
||||
printf("Débit calculé : %d Mb/s\n", debit);
|
||||
printf("[DEBUG] delta : %d us, tsfr : %d\n", delta, tsfr);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Arguments parsing
|
||||
if (argc != 2) {
|
||||
utilisation();
|
||||
}
|
||||
if (*argv[1] == 's') {
|
||||
server();
|
||||
} else if (*argv[1] == 'c') {
|
||||
client();
|
||||
} else {
|
||||
utilisation();
|
||||
}
|
||||
}
|
||||
111
TP/TP2/main.c
Normal file
111
TP/TP2/main.c
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define KEY 30
|
||||
|
||||
/*
|
||||
* TP 2 partie sémaphore OK.
|
||||
* L'exclusion mutuelle est observée correctement.
|
||||
* Lancez d'abord le serveur puis le client.
|
||||
* Si echec, essayez de changer la clé.
|
||||
*/
|
||||
|
||||
void utilisation() {
|
||||
printf("Usage : ./a.out [c] [s]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void server() {
|
||||
int key = KEY;
|
||||
int init = 1;
|
||||
char recv[1];
|
||||
struct sembuf op;
|
||||
int sem = semget((key_t)key, 1, 666 | IPC_CREAT);
|
||||
|
||||
if (sem < 0) {
|
||||
printf("Erreur création sémaphore.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (semctl(sem, 0, SETVAL, init) == -1) {
|
||||
printf("Erreur initialisation sémaphore.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
op.sem_num = 0;
|
||||
op.sem_flg = 0;
|
||||
|
||||
while (1) {
|
||||
op.sem_op = -1;
|
||||
printf("Serveur en attente...\n");
|
||||
if (semop(sem, &op, 1)) {
|
||||
printf("Erreur attente.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("Le serveur a la main. Entrez qqc : ");
|
||||
fgets(recv, 10, stdin);
|
||||
|
||||
op.sem_op = 1;
|
||||
printf("Le serveur rend la main.\n");
|
||||
if (semop(sem, &op, 1)) {
|
||||
printf("Erreur op.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void client() {
|
||||
int key = KEY;
|
||||
int init = 0;
|
||||
char recv[1];
|
||||
struct sembuf op;
|
||||
int sem = semget((key_t)key, 0, 0);
|
||||
|
||||
if (sem < 0) {
|
||||
printf("Erreur création sémaphore.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
op.sem_num = 0;
|
||||
op.sem_flg = 0;
|
||||
|
||||
while (1) {
|
||||
op.sem_op = -1;
|
||||
printf("Client en attente...\n");
|
||||
if (semop(sem, &op, 1)) {
|
||||
printf("Erreur attente.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("Le client a la main. Entrez qqc : ");
|
||||
fgets(recv, 10, stdin);
|
||||
|
||||
op.sem_op = 1;
|
||||
printf("Le client rend la main.\n");
|
||||
if (semop(sem, &op, 1)) {
|
||||
printf("Erreur op.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
// Arguments parsing
|
||||
if (argc != 2) {
|
||||
utilisation();
|
||||
}
|
||||
if (*argv[1] == 's') {
|
||||
server();
|
||||
} else if (*argv[1] == 'c') {
|
||||
client();
|
||||
} else {
|
||||
utilisation();
|
||||
}
|
||||
}
|
||||
195
TP/TP2/shared_mem.c
Normal file
195
TP/TP2/shared_mem.c
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define KEY 160
|
||||
#define NB_ITERATION 100000
|
||||
|
||||
/*
|
||||
* TP2 Partie 3 Communication par mémoire partagée
|
||||
* On observe une alternance correct et derterministe.
|
||||
* Le débit calculé est cohérent
|
||||
*/
|
||||
|
||||
void utilisation() {
|
||||
printf("Usage : ./a.out [c] [s]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int server = -1;
|
||||
struct timeval begin, end;
|
||||
|
||||
// Variables SHM
|
||||
int key_shm = KEY;
|
||||
int *shm = NULL;
|
||||
int shmid = 0;
|
||||
|
||||
// Variables IPC
|
||||
int key = KEY;
|
||||
int init_s = 0;
|
||||
int init_c = 1;
|
||||
char recv[1];
|
||||
struct sembuf op;
|
||||
int sem_s, sem_c;
|
||||
|
||||
/* Traitement des arguments */
|
||||
if (argc != 2) {
|
||||
utilisation();
|
||||
}
|
||||
if (*argv[1] == 's') {
|
||||
server = 1;
|
||||
sem_s = semget((key_t)key, 1, 666 | IPC_CREAT);
|
||||
sem_c = semget((key_t)key+1, 1, 666 | IPC_CREAT);
|
||||
} else if (*argv[1] == 'c') {
|
||||
sem_s = semget((key_t)key, 0, 0);
|
||||
sem_c = semget((key_t)key+1, 0, 0);
|
||||
server = 0;
|
||||
} else {
|
||||
utilisation();
|
||||
}
|
||||
|
||||
/* Création du sémaphore */
|
||||
if (sem_s < 0 || sem_c < 0) {
|
||||
printf("Erreur création sémaphore.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Initialisation du sémaphore */
|
||||
if (server) {
|
||||
if (semctl(sem_s, 0, SETVAL, init_s) == -1 || semctl(sem_c, 0, SETVAL, init_c) == -1) {
|
||||
printf("Erreur initialisation sémaphore.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
op.sem_num = 0;
|
||||
op.sem_flg = 0;
|
||||
|
||||
/* Création de la SHM */
|
||||
if (!(shmid = shmget((key_t)key_shm, 4, 0666 | IPC_CREAT))) {
|
||||
printf("Erreur création SHM.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Attachement de la shm */
|
||||
if (!(shm = (int *)shmat(shmid, 0, 0))) {
|
||||
printf("Erreur attache SHM.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
////////SERVER////////
|
||||
if (server) {
|
||||
printf("Mode serveur.\n");
|
||||
|
||||
for (int i = 0; i < (NB_ITERATION/2); ++i) {
|
||||
op.sem_op = -1;
|
||||
//printf("Serveur en attente...\n");
|
||||
if (semop(sem_s, &op, 1)) {
|
||||
printf("Erreur attente.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//printf("On incrémente le shm...");
|
||||
(*shm)++;
|
||||
//printf("Fait.\n");
|
||||
//sleep(1);
|
||||
|
||||
op.sem_op = 1;
|
||||
//printf("Le serveur rend la main.\n");
|
||||
if (semop(sem_c, &op, 1)) {
|
||||
printf("Erreur op.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////CLIENT////////
|
||||
else {
|
||||
printf("Mode client.\n");
|
||||
printf("Lancement du chronometre.\n");
|
||||
gettimeofday(&begin, NULL);
|
||||
|
||||
|
||||
for (int i = 0; i < (NB_ITERATION/2); ++i) {
|
||||
op.sem_op = -1;
|
||||
//printf("Client en attente...\n");
|
||||
if (semop(sem_c, &op, 1)) {
|
||||
printf("Erreur attente.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//printf("On incrémente le shm...");
|
||||
(*shm)++;
|
||||
//printf("Fait.\n");
|
||||
//sleep(1);
|
||||
|
||||
//printf("Le client rend la main.\n");
|
||||
op.sem_op = 1;
|
||||
if (semop(sem_s, &op, 1)) {
|
||||
printf("Erreur op.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
gettimeofday(&end, NULL);
|
||||
op.sem_op = -1;
|
||||
if (semop(sem_c, &op, 1)) {
|
||||
printf("Erreur attente.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("Valeur finale SHM : %d\n", *shm);
|
||||
/* detache la SHM */
|
||||
if (shmdt(shm)) {
|
||||
printf("Erreur détachement.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!server) {
|
||||
/* Destruction SHM */
|
||||
if (shmctl(shmid, IPC_RMID, 0)) {
|
||||
printf("Erreur destruction SHM.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Libération sémaphore */
|
||||
if (semctl(sem_s, 0, IPC_RMID, 0) || semctl(sem_c, 0, IPC_RMID, 0)) {
|
||||
printf("Erreur libération sémaphore.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Calcul débit*/
|
||||
int delta =
|
||||
((end.tv_sec - begin.tv_sec) * 1000000L + end.tv_usec) - begin.tv_usec;
|
||||
int debit =
|
||||
(NB_ITERATION * 2 * sizeof(int) * 8) / (delta); // (delta est déjà en us)
|
||||
|
||||
printf("Débit calculé : %d Mb/s\n", debit);
|
||||
}
|
||||
|
||||
printf("Fin.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
if (server) {
|
||||
printf("Affectation de la valeur par le serveur.\n");
|
||||
*shm = 10;
|
||||
|
||||
sleep(10);
|
||||
printf("Nouvelle valeur lue par le serveur : %d\n", *shm);
|
||||
}
|
||||
else {
|
||||
printf("Valeur lue par le client : %d\n", *shm);
|
||||
*shm = 28;
|
||||
printf("Valeur modifiée par le client : %d\n", *shm);
|
||||
}
|
||||
|
||||
*/
|
||||
174
TP/TP3/calcul.c
Normal file
174
TP/TP3/calcul.c
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define D 1000
|
||||
|
||||
/*
|
||||
* TP 3
|
||||
* 1) Fait et ok.
|
||||
* 2) Fait et ok. On constate que la seconde méthode est plus longue.
|
||||
* 3) Ça ne donne pas la bonne valeur : il faut proteger l'incrémentation par un mutex
|
||||
* 4) On constate que le temps de'exécution augmente de manière exp.
|
||||
*/
|
||||
|
||||
|
||||
int V[D];
|
||||
int V_plus[D];
|
||||
int A[D][D];
|
||||
int t_num = 0;
|
||||
|
||||
int compt_glob = 0;
|
||||
|
||||
|
||||
void err_args() {
|
||||
printf("[~] Usage: calcul [-m [1|2]] [-t #] [-i ##]\n");
|
||||
printf("Aide :\n -i [ITÉRATIONS]\n -m [MÉTHODE]\n -t [THREAD] (max: 16)\n -v, verbose output\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
void * fn_thread_m1 (void * p_int) {
|
||||
int nb_t = *(int *) p_int;
|
||||
int lt = (D / nb_t) + 1;
|
||||
int num = t_num;
|
||||
++t_num;
|
||||
|
||||
for (int i = num * lt; i < (num+1)*lt && i < D; ++i){
|
||||
for (int j = 0; j < D; ++j){
|
||||
V_plus[i] += V[j] * A[i][j];
|
||||
//compt_glob++;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
void * fn_thread_m2 (void * p_int) {
|
||||
int nb_t = *(int *) p_int;
|
||||
int lt = (D / nb_t) + 1;
|
||||
int num = t_num;
|
||||
++t_num;
|
||||
|
||||
for (int j = 0; j < D; ++j){
|
||||
for (int i = num * lt; i < (num+1)*lt && i < D; ++i){
|
||||
V_plus[i] += A[i][j] * V[j];
|
||||
//compt_glob++;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
// On parse les arguments
|
||||
int c;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int method = -1;
|
||||
int nb_t = -1;
|
||||
int ite = -1;
|
||||
int v = 0; //verbose
|
||||
|
||||
|
||||
while ((c = getopt(argc, argv, "m:t:i:v")) != -1) {
|
||||
switch (c) {
|
||||
case 'm':
|
||||
method = atoi(optarg);
|
||||
if (method != 1 && method != 2) err_args();
|
||||
break;
|
||||
|
||||
case 't':
|
||||
nb_t = atoi(optarg);
|
||||
if (nb_t > 16) err_args();
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
ite = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
v = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
err_args();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (method < 0 || nb_t < 0 || ite < 0) err_args();
|
||||
|
||||
printf("Lancement du programme...\nMéthode %d, %d thread(s) et %d itération(s)\n", method, nb_t, ite);
|
||||
|
||||
//Fichier de sauvegarde
|
||||
FILE* fichier = NULL;
|
||||
fichier = fopen("calcul.txt", "w");
|
||||
fprintf(fichier, "Méthode %d - %d thread(s) - %d itération(s)\n", method, nb_t, ite);
|
||||
|
||||
//On initialise les tableaux
|
||||
//srand(time(NULL));
|
||||
if (!v) goto no_verbose1;
|
||||
srand(0);
|
||||
for (int i = 0; i < D; ++i){
|
||||
V[i] = (rand() % 20) - 10;
|
||||
V_plus[i] = 0;
|
||||
for (int j = 0; j < D; ++j)
|
||||
A[i][j] = (rand() % 20) - 10;
|
||||
}
|
||||
|
||||
printf("Tableaux initialisés : \nV(0) = [ ");
|
||||
for (int i = 0; i < D; ++i)
|
||||
printf("%d, ", V[i]);
|
||||
printf("]\n");
|
||||
|
||||
printf("A = [\n");
|
||||
for (int i = 0; i < D; ++i){
|
||||
for (int j = 0; j < D; ++j)
|
||||
printf("%d, ", A[i][j]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
no_verbose1:
|
||||
;
|
||||
struct timeval begin, end;
|
||||
gettimeofday(&begin, NULL);
|
||||
|
||||
pthread_t threads[nb_t];
|
||||
for (int it = 0; it < ite; ++it){
|
||||
// Lancement des threads en fonction de la méthode
|
||||
for (int j = 0; j < nb_t; ++j) {
|
||||
if (method == 1) pthread_create(&threads[j], NULL, fn_thread_m1, (void*) &nb_t);
|
||||
else pthread_create(&threads[j], NULL, fn_thread_m2, (void*) &nb_t);
|
||||
}
|
||||
|
||||
// On attend que tout les threads finissent leur partie
|
||||
for (int i = 0; i < nb_t; ++i) pthread_join(threads[i], NULL);
|
||||
for (int i = 0; i < D; ++i) {V[i] = V_plus[i]; V_plus[i] = 0;}
|
||||
t_num = 0;
|
||||
|
||||
// On affiche le vecteur calculé
|
||||
if (!v) goto no_verbose2;
|
||||
printf("V(%d) = [ ", it + 1);
|
||||
for (int i = 0; i < D; ++i)
|
||||
printf("%d, ", V[i]);
|
||||
printf("]\n");
|
||||
no_verbose2:;
|
||||
}
|
||||
|
||||
gettimeofday(&end, NULL);
|
||||
printf("Time: %ld microseconds\n", ((end.tv_sec - begin.tv_sec)*1000000L + end.tv_usec) - begin.tv_usec);
|
||||
printf("Nombre d'opération arithmétique : %d\n", compt_glob);
|
||||
|
||||
printf("Enregistrement...");
|
||||
fprintf(fichier, "Temps d'exécution : %ld\n", ((end.tv_sec - begin.tv_sec)*1000000L + end.tv_usec) - begin.tv_usec);
|
||||
fclose(fichier);
|
||||
printf("fait.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue