changement du fichier tp scr
This commit is contained in:
46
TP_SCR3.1/TP_Fichiers/cp_stdio_ultra.c
Normal file
46
TP_SCR3.1/TP_Fichiers/cp_stdio_ultra.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <stdio.h> // pour printf, fprintf, fopen, fread, fwrite, fclose
|
||||
#include <stdlib.h> // pour exit()
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
FILE *source, *dest; // pointeurs de fichiers
|
||||
char c; // variable pour stocker un octet lu
|
||||
|
||||
// Vérifier que l'utilisateur a bien fourni deux arguments (source et destination)
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <fichier_source> <fichier_dest>\n", argv[0]);
|
||||
exit(1); // quitte le programme avec code d'erreur
|
||||
}
|
||||
|
||||
// Ouvrir le fichier source en mode lecture binaire ("rb")
|
||||
source = fopen(argv[1], "rb");
|
||||
if (source == NULL) { // si l'ouverture échoue
|
||||
perror("Erreur ouverture source");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Ouvrir ou créer le fichier destination en mode écriture binaire ("wb")
|
||||
dest = fopen(argv[2], "wb");
|
||||
if (dest == NULL) { // si l'ouverture échoue
|
||||
perror("Erreur ouverture destination");
|
||||
fclose(source); // on ferme le fichier source déjà ouvert
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Lire un octet depuis le fichier source puis l'écrire dans le fichier destination
|
||||
while (fread(&c, 1, 1, source) == 1) {
|
||||
if (fwrite(&c, 1, 1, dest) != 1) {
|
||||
perror("Erreur écriture");
|
||||
fclose(source);
|
||||
fclose(dest);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Fermer les deux fichiers
|
||||
fclose(source);
|
||||
fclose(dest);
|
||||
|
||||
// Indiquer que la copie s'est terminée correctement
|
||||
printf("Copie terminée (méthode stdio).\n");
|
||||
return 0; // programme terminé sans erreur
|
||||
}
|
||||
49
TP_SCR3.1/TP_Fichiers/cp_syscall.c
Normal file
49
TP_SCR3.1/TP_Fichiers/cp_syscall.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <stdio.h> // pour perror() et printf() : fonctions d’affichage
|
||||
#include <stdlib.h> // pour exit() : permet de quitter le programme en cas d’erreur
|
||||
#include <fcntl.h> // pour open() : ouverture de fichiers
|
||||
#include <unistd.h> // pour read(), write(), close() : appels systèmes bas niveau
|
||||
|
||||
int main() {
|
||||
int source, dest; // "descripteurs de fichiers" : nombres entiers utilisés par le système
|
||||
char c; // variable qui va contenir un caractère (1 octet) lu depuis le fichier
|
||||
|
||||
// Ouvrir le fichier source en lecture seule (O_RDONLY)
|
||||
source = open("source.txt", O_RDONLY);
|
||||
if (source < 0) { // si la valeur < 0, c’est que l’ouverture a échoué
|
||||
perror("Erreur ouverture source"); // affiche l’erreur système
|
||||
exit(1); // quitte le programme avec un code d’erreur
|
||||
}
|
||||
|
||||
// Créer (si n’existe pas) ou ouvrir le fichier destination en écriture
|
||||
// O_WRONLY = écriture seule
|
||||
// O_CREAT = créer le fichier si n’existe pas
|
||||
// O_TRUNC = vider le fichier s’il existe déjà
|
||||
// 0644 = permissions du fichier (rw-r--r--)
|
||||
dest = open("dest.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (dest < 0) { // si l’ouverture échoue
|
||||
perror("Erreur ouverture destination");
|
||||
close(source); // on ferme quand même le fichier source ouvert
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Lire et écrire le fichier octet par octet
|
||||
// read(source, &c, 1) lit 1 octet du fichier source et le stocke dans c
|
||||
// la boucle continue tant que read() lit bien 1 octet
|
||||
while (read(source, &c, 1) == 1) {
|
||||
// écrire cet octet dans le fichier destination
|
||||
if (write(dest, &c, 1) != 1) { // si write() échoue
|
||||
perror("Erreur écriture");
|
||||
close(source);
|
||||
close(dest);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Fermer les deux fichiers
|
||||
close(source);
|
||||
close(dest);
|
||||
|
||||
// Indiquer à l’utilisateur que tout s’est bien passé
|
||||
printf("Copie terminée (méthode appels système).\n");
|
||||
return 0; // programme terminé correctement
|
||||
}
|
||||
0
TP_SCR3.1/TP_Fichiers/untitled
Normal file
0
TP_SCR3.1/TP_Fichiers/untitled
Normal file
BIN
TP_SCR3.1/TP_Memoire/buf
Executable file
BIN
TP_SCR3.1/TP_Memoire/buf
Executable file
Binary file not shown.
9
TP_SCR3.1/TP_Memoire/buf.c
Normal file
9
TP_SCR3.1/TP_Memoire/buf.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "helpers.h"
|
||||
|
||||
static char buffer[16 MB] = {0};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
randomize(buffer, 16 MB);
|
||||
return interlude();
|
||||
}
|
||||
8
TP_SCR3.1/TP_Memoire/heap.c
Normal file
8
TP_SCR3.1/TP_Memoire/heap.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "helpers.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
dirty(16 MB);
|
||||
clean(32 MB);
|
||||
return interlude();
|
||||
}
|
||||
BIN
TP_SCR3.1/TP_Memoire/heap.o
Normal file
BIN
TP_SCR3.1/TP_Memoire/heap.o
Normal file
Binary file not shown.
36
TP_SCR3.1/TP_Memoire/helpers.c
Normal file
36
TP_SCR3.1/TP_Memoire/helpers.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "helpers.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void randomize(char *buf, size_t n)
|
||||
{
|
||||
assert(buf);
|
||||
memset(buf, rand() & 0xff, n);
|
||||
}
|
||||
|
||||
void clean(size_t b)
|
||||
{
|
||||
for (; b > 0; b -= 1 KB)
|
||||
calloc(1 KB, sizeof(char));
|
||||
}
|
||||
|
||||
void dirty(size_t b)
|
||||
{
|
||||
for (; b > 0; b -= 1 KB)
|
||||
randomize(calloc(1 KB, sizeof(char)), 1 KB);
|
||||
}
|
||||
|
||||
int interlude(void)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
printf("pid %i\n", (int)pid);
|
||||
printf("------------------------------------------\n"
|
||||
"go check /proc/%i/smaps; I'll wait...\n"
|
||||
"press <Enter> when you're done\n", pid);
|
||||
fgetc(stdin);
|
||||
return 0;
|
||||
}
|
||||
13
TP_SCR3.1/TP_Memoire/helpers.h
Normal file
13
TP_SCR3.1/TP_Memoire/helpers.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _HELPERS_H
|
||||
#define _HELPERS_H
|
||||
#include <stdlib.h>
|
||||
|
||||
#define KB * 1024
|
||||
#define MB * 1024 * 1024
|
||||
|
||||
void randomize(char *buf, size_t n);
|
||||
void clean(size_t n);
|
||||
void dirty(size_t n);
|
||||
int interlude(void);
|
||||
|
||||
#endif
|
||||
BIN
TP_SCR3.1/TP_Memoire/helpers.o
Normal file
BIN
TP_SCR3.1/TP_Memoire/helpers.o
Normal file
Binary file not shown.
12
TP_SCR3.1/TP_Memoire/huge.c
Normal file
12
TP_SCR3.1/TP_Memoire/huge.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "helpers.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *under = malloc(96 KB);
|
||||
randomize(under, 96 KB);
|
||||
|
||||
char *over = malloc(256 KB);
|
||||
randomize(over, 256 KB);
|
||||
|
||||
return interlude();
|
||||
}
|
||||
27
TP_SCR3.1/TP_Memoire/memoire.c
Normal file
27
TP_SCR3.1/TP_Memoire/memoire.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* adresses virtuelles d'un processus */
|
||||
|
||||
#include<stdio.h>
|
||||
#include<sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include<unistd.h>
|
||||
#include<stdlib.h>
|
||||
|
||||
int t[1000] = {[0 ... 999] = 2};
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int i=3;
|
||||
static int j = 3;
|
||||
char * m = (char*)malloc(1);
|
||||
printf("je suis le pid %d\n\n",getpid());
|
||||
/* ------- Affichage des adresses --------*/
|
||||
printf("main\t\t=\t%p\n",main);
|
||||
printf("gettimeofday\t=\t%p\n",gettimeofday);
|
||||
printf("&argc\t\t=\t%p\n",&argc);
|
||||
printf("&i\t\t=\t%p\n",&i);
|
||||
printf("&j\t\t=\t%p\n",&j);
|
||||
printf("t\t\t=\t%p\n",t);
|
||||
printf("m\t\t=\t%p\n",m);
|
||||
|
||||
getchar();
|
||||
}
|
||||
38
TP_SCR3.1/TP_Memoire/mmap.c
Normal file
38
TP_SCR3.1/TP_Memoire/mmap.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "helpers.h"
|
||||
#include <sys/mman.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* inert map (never modified) */
|
||||
char *inert = mmap(NULL, 16 KB,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE,
|
||||
-1, 0);
|
||||
/* anonymous, private mmap */
|
||||
char *anon_priv = mmap(NULL, 32 KB,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE,
|
||||
-1, 0);
|
||||
randomize(anon_priv, 32 KB);
|
||||
|
||||
/* anonymous, shared map */
|
||||
char *anon_shared = mmap(NULL, 64 KB,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_SHARED,
|
||||
-1, 0);
|
||||
randomize(anon_shared, 64 KB);
|
||||
|
||||
/* private, file-backed map */
|
||||
int fd = open("data/256k", O_RDWR);
|
||||
assert(fd >= 0);
|
||||
char *file = mmap(NULL, 256 KB,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE,
|
||||
fd, 0);
|
||||
randomize(file, 128 KB);
|
||||
|
||||
return interlude();
|
||||
}
|
||||
6
TP_SCR3.1/TP_Memoire/null.c
Normal file
6
TP_SCR3.1/TP_Memoire/null.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "helpers.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return interlude();
|
||||
}
|
||||
8
TP_SCR3.1/TP_Memoire/stack.c
Normal file
8
TP_SCR3.1/TP_Memoire/stack.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "helpers.h"
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
char buf[28 KB] = {0};
|
||||
randomize(buf, 28 KB);
|
||||
return interlude();
|
||||
}
|
||||
180
TP_SCR3.1/TP_Memoire/tp-reponses-yolou.txt
Normal file
180
TP_SCR3.1/TP_Memoire/tp-reponses-yolou.txt
Normal file
@@ -0,0 +1,180 @@
|
||||
TP1 MEMOIRE - YOLOU
|
||||
|
||||
1. Ce que je dois comprendre sur le code le processus possède une mémoire qui contient des adresses virtuelles
|
||||
vdsco ce sont des appels systeme y'en a que 4 get of day c'est un appel systeme, le prgramme considere que c'est un appel systeme mais ca n'utilise pas l'organisation du noyaux (sauvegarde, rechargement etc...)
|
||||
|
||||
[yolou@salle223-10 TP_Memoire]$ ./a.out
|
||||
je suis le pid 23540
|
||||
|
||||
main = 0x559308d20179
|
||||
gettimeofday = 0x7f08d7032870
|
||||
&argc = 0x7ffd6bca825c
|
||||
&i = 0x7ffd6bca826c
|
||||
&j = 0x559308d24000
|
||||
t = 0x559308d23060
|
||||
m = 0x559320a82310
|
||||
^Z
|
||||
[1]+ Stopped ./a.out
|
||||
[yolou@salle223-10 TP_Memoire]$ cat /proc/23540/maps
|
||||
|
||||
adresse début adresse fin perms offset devices inode chemin
|
||||
559308d1f000-559308d20000 r--p 00000000 00:3e (périphèrique) 70729069 /export/home/info-but24/yolou/BUT2/TP_SCR/TP_Memoire/a.out
|
||||
559308d20000-559308d21000 r-xp 00001000 00:3e 70729069 /export/home/info-but24/yolou/BUT2/TP_SCR/TP_Memoire/a.out
|
||||
559308d21000-559308d22000 r--p 00002000 00:3e 70729069 /export/home/info-but24/yolou/BUT2/TP_SCR/TP_Memoire/a.out
|
||||
559308d22000-559308d23000 r--p 00002000 00:3e 70729069 /export/home/info-but24/yolou/BUT2/TP_SCR/TP_Memoire/a.out
|
||||
559308d23000-559308d25000 rw-p 00003000 00:3e 70729069 /export/home/info-but24/yolou/BUT2/TP_SCR/TP_Memoire/a.out
|
||||
559320a82000-559320aa3000 rw-p 00000000 00:00 0 [heap]
|
||||
7f08d6c00000-7f08d6c24000 r--p 00000000 103:05 6028 /usr/lib/libc.so.6
|
||||
7f08d6c24000-7f08d6d96000 r-xp 00024000 103:05 6028 /usr/lib/libc.so.6
|
||||
7f08d6d96000-7f08d6e05000 r--p 00196000 103:05 6028 /usr/lib/libc.so.6
|
||||
7f08d6e05000-7f08d6e09000 r--p 00204000 103:05 6028 /usr/lib/libc.so.6
|
||||
7f08d6e09000-7f08d6e0b000 rw-p 00208000 103:05 6028 /usr/lib/libc.so.6
|
||||
7f08d6e0b000-7f08d6e13000 rw-p 00000000 00:00 0
|
||||
7f08d6ffb000-7f08d7000000 rw-p 00000000 00:00 0
|
||||
7f08d702c000-7f08d7030000 r--p 00000000 00:00 0 [vvar]
|
||||
7f08d7030000-7f08d7032000 r--p 00000000 00:00 0 [vvar_vclock]
|
||||
7f08d7032000-7f08d7034000 r-xp 00000000 00:00 0 [vdso]
|
||||
7f08d7034000-7f08d7035000 r--p 00000000 103:05 6019 /usr/lib/ld-linux-x86-64.so.2 (=> mappage dans le disque dur, quand on invoque le printf etc c'est ici qu'il vient ressourcer)
|
||||
7f08d7035000-7f08d705f000 r-xp 00001000 103:05 6019 /usr/lib/ld-linux-x86-64.so.2
|
||||
7f08d705f000-7f08d706d000 r--p 0002b000 103:05 6019 /usr/lib/ld-linux-x86-64.so.2
|
||||
7f08d706d000-7f08d706f000 r--p 00039000 103:05 6019 /usr/lib/ld-linux-x86-64.so.2
|
||||
7f08d706f000-7f08d7070000 rw-p 0003b000 103:05 6019 /usr/lib/ld-linux-x86-64.so.2
|
||||
7f08d7070000-7f08d7071000 rw-p 00000000 00:00 0
|
||||
7ffd6bc89000-7ffd6bcaa000 rw-p 00000000 00:00 0 [stack]
|
||||
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
|
||||
|
||||
|
||||
Bibliotheque dynamique dln windows /
|
||||
Bibl. standard C libsc :
|
||||
|
||||
. La libc contient les fonctions comme printf, malloc, exit...
|
||||
|
||||
. PLusieurs segment comme :
|
||||
|
||||
. r-xp = code éxécutable de la bibliothèque
|
||||
. r-p = données en lecture seule
|
||||
. rw-p = données globales de la libc.
|
||||
|
||||
[vvar] :
|
||||
|
||||
. Virtual Variables : zone créée par le noyau pour partager certaines infos comme l'horloge entre le noyau et ton programme
|
||||
. Lecture seule.
|
||||
|
||||
id-linux (linker dynamique) :
|
||||
|
||||
Le chargeur dynamique : c'est lui qui charge les biblio partagé comme libc en mémoire
|
||||
Il est obligatoire pour éxécuter un programme avec des bibliothèques dynamiques
|
||||
|
||||
[stack] (pile) :
|
||||
|
||||
La pile du processus
|
||||
Sert a stocker : variable locales, adresse de retour des fonctions, parametres.
|
||||
Grandit quand tu appelles des fonctions imbriquées.
|
||||
|
||||
|
||||
Adresse-debut/fin = adresses virtuelles
|
||||
il y a les perms : r-xp = lecture + execution -> segment code
|
||||
r-p = lecture seul -> constantes
|
||||
rw-p = lecture/écriture -> variables globales initialisées
|
||||
Virtual Dymanic Shared Object => Petite zone pour accelerer certains appels systeme (ex gettimeofday) = vsdo
|
||||
|
||||
Heap(tas) :
|
||||
|
||||
. zone utilisée pour les allocations dynamiques(malloc,callocfree)
|
||||
. grandit ou rétrécit selon les besoins.
|
||||
|
||||
|
||||
2)
|
||||
|
||||
Apres avoir fait la commande pmap -x <piud>, j'observe que il y'a plusieurs adresses :
|
||||
|
||||
Addresss -> l'adresse virtuelle oû commence ce segment mémoire
|
||||
Kbytes -> taille totale du segments (réservée)
|
||||
RSS (Resident Set Size) -> combien de mémoire de ce segment est réellement physqiuement en RAM (le reste peut etre sur disque ou pas encore utilisé) pour savoir si elle sont mappé physiquement
|
||||
Dirty -> nombre de Kilo octet modifiés (non partagés, spécifiques à mon processus)
|
||||
Mode -> permission du segment :
|
||||
r, w, x, s ou p : partagé (shared) ou prié (private)
|
||||
Mapping -> d'oû vient ce segment (exécutable a.out, biblliothèque, [stack], [heap], [anone] pour anonyme)
|
||||
|
||||
Typiquement avec le prgramme du premier exo :
|
||||
|
||||
113416: ./a.out
|
||||
Address Kbytes RSS Dirty Mode Mapping
|
||||
000055c06db68000 4 4 0 r---- a.out
|
||||
000055c06db69000 4 4 0 r-x-- a.out
|
||||
000055c06db6a000 4 4 0 r---- a.out
|
||||
000055c06db6b000 4 4 4 r---- a.out
|
||||
000055c06db6c000 8 8 8 rw--- a.out
|
||||
000055c091c49000 132 4 4 rw--- [ anon ]
|
||||
00007f0f90000000 144 144 0 r---- libc.so.6
|
||||
00007f0f90024000 1480 1060 0 r-x-- libc.so.6
|
||||
00007f0f90196000 444 128 0 r---- libc.so.6
|
||||
00007f0f90205000 16 16 16 r---- libc.so.6
|
||||
00007f0f90209000 8 8 8 rw--- libc.so.6
|
||||
00007f0f9020b000 32 20 20 rw--- [ anon ]
|
||||
00007f0f903f9000 20 12 12 rw--- [ anon ]
|
||||
00007f0f9042b000 16 0 0 r---- [ anon ]
|
||||
00007f0f9042f000 8 0 0 r---- [ anon ]
|
||||
00007f0f90431000 8 8 0 r-x-- [ anon ]
|
||||
00007f0f90433000 4 4 0 r---- ld-linux-x86-64.so.2
|
||||
00007f0f90434000 168 168 0 r-x-- ld-linux-x86-64.so.2
|
||||
00007f0f9045e000 56 56 0 r---- ld-linux-x86-64.so.2
|
||||
00007f0f9046c000 8 8 8 r---- ld-linux-x86-64.so.2
|
||||
00007f0f9046e000 4 4 4 rw--- ld-linux-x86-64.so.2
|
||||
00007f0f9046f000 4 4 4 rw--- [ anon ]
|
||||
00007ffc6a1a9000 132 12 12 rw--- [ stack ]
|
||||
ffffffffff600000 4 0 0 --x-- [ anon ]
|
||||
---------------- ------- ------- -------
|
||||
total kB 2712 1680 100
|
||||
|
||||
|
||||
1. a.out (mon prgm)
|
||||
|
||||
Aplusieurs lignes avec a.out :
|
||||
|
||||
r-x -> segment code exécutable
|
||||
r-- -> données en lecture seule (constates)
|
||||
rw- -> données globales modifiables
|
||||
|
||||
2. [anone] (anonyme)
|
||||
|
||||
Memoire réservée par le processus sans fichier associé
|
||||
Ici ca peut etre des petit malloc
|
||||
|
||||
3. libc.so.6
|
||||
|
||||
La bibliothèque standard du C (printf,malloc, ...).
|
||||
.r-x -> code éxécutable de la libc
|
||||
. rw- -> données de la libc
|
||||
|
||||
4. Id-linux x86-64.so.2
|
||||
|
||||
Le chargeur dynamique qui charge les bibliothèque
|
||||
Lui aussi a code (r-x) et données (rw-).
|
||||
|
||||
total kB : 2712
|
||||
|
||||
Le processus occupe environ 2.7 Mo au total.
|
||||
|
||||
Sur ces 2712 Ko, 1680 Ko sont effectivement en RAM (RSS).
|
||||
|
||||
Le reste peut etre reservé mais pas encore utilisé.
|
||||
|
||||
Généralement, le programme est découpé en segments mémoire : code, données, heap, pile, bibliothéques, mappings, anonymes.
|
||||
|
||||
La commande pmap -x permet de voir :
|
||||
|
||||
combien est réservé (Kbvtes) le processus,
|
||||
cobmien est vraiment en RAM (RSS),
|
||||
combien est spécifique au processus (Dirty)
|
||||
et pour finir l'origine du segment (Mapping)
|
||||
|
||||
Ca illustre le cours le cours sur l'organisation mémoire d'un processus et la gestion par Linux via mémoire vituelle + MMU (MMU pour memory management unit), un composant informatique responsable de l'accès à la mémoire demandée par le processeur).
|
||||
|
||||
Pour le code buf :
|
||||
|
||||
Pour les segments "buf" (l'executable)
|
||||
|
||||
Plusierus petites lignes de 4kB avec buf :
|
||||
|
||||
r-x -> code éxécutable
|
||||
BIN
TP_SCR3.1/TP_SIGNAUX/parexec
Executable file
BIN
TP_SCR3.1/TP_SIGNAUX/parexec
Executable file
Binary file not shown.
36
TP_SCR3.1/TP_SIGNAUX/parexec.c
Normal file
36
TP_SCR3.1/TP_SIGNAUX/parexec.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// TODO
|
||||
assert(argc >= 2);
|
||||
|
||||
// char prog = argv[1];
|
||||
|
||||
for(int i=2; i<argc; i++){
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if(pid == 0){
|
||||
execlp(argv[1], argv[1], argv[i], NULL);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
for(int i=2; i<argc; i++){
|
||||
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
119
TP_SCR3.1/TP_SIGNAUX/parexeclim.c
Normal file
119
TP_SCR3.1/TP_SIGNAUX/parexeclim.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* parexec_lim.c
|
||||
* Q3 : Lancer au plus N instances en parallèle : ./parexec_lim prog N arg1 [arg2 ...]
|
||||
* Q4 : Si une instance se termine à cause d'un SIGNAL -> tuer toutes les autres et arrêter.
|
||||
*/
|
||||
|
||||
#include <stdio.h> // fprintf, perror
|
||||
#include <stdlib.h> // atoi, calloc, free, EXIT_*
|
||||
#include <unistd.h> // fork, execlp, usleep
|
||||
#include <sys/wait.h> // wait, WIFSIGNALED, WTERMSIG
|
||||
#include <signal.h> // kill
|
||||
#include <errno.h> // errno
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Vérifie la syntaxe minimale : prog + N + au moins 1 argument pour prog
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "Usage: %s prog N arg1 [arg2 ...]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
char *prog = argv[1]; // le programme à lancer (ex: "./rebours")
|
||||
int N = atoi(argv[2]); // nombre maximum d'enfants en parallèle
|
||||
if (N <= 0) { // N doit être strictement positif
|
||||
fprintf(stderr, "N doit être > 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int next = 3; // index du prochain argument à donner à prog (argv[3] au début)
|
||||
int running = 0; // nombre d'enfants actuellement en cours d'exécution
|
||||
int stop = 0; // =1 si on a détecté une fin anormale -> on arrête de relancer
|
||||
|
||||
// Tableau des PIDs des enfants "actifs" (taille N). 0 signifie "case libre".
|
||||
pid_t *slots = calloc((size_t)N, sizeof(pid_t));
|
||||
if (!slots) { perror("calloc"); return EXIT_FAILURE; }
|
||||
|
||||
// ===== 1) Lancer tout de suite jusqu'à N enfants (ou jusqu'à épuisement des args) =====
|
||||
while (!stop && running < N && next < argc) {
|
||||
pid_t pid = fork(); // crée un nouveau processus
|
||||
if (pid == 0) { // dans l'enfant
|
||||
execlp(prog, prog, argv[next], NULL); // remplace l'enfant par "prog argi"
|
||||
_exit(127); // si exec échoue, sortir avec code 127
|
||||
}
|
||||
if (pid < 0) { // fork a échoué dans le parent
|
||||
perror("fork");
|
||||
stop = 1; // on arrête les lancements
|
||||
break;
|
||||
}
|
||||
// Ici on est dans le parent et fork a réussi : on mémorise le PID dans une case libre 2 5 4 3
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (slots[i] == 0) { // 0 = case libre
|
||||
slots[i] = pid; // on range ce PID
|
||||
break;
|
||||
}
|
||||
}
|
||||
running++; // on a un enfant de plus
|
||||
next++; // prochain argument à utiliser
|
||||
}
|
||||
|
||||
// ===== 2) Boucle principale : attendre les fins, réagir, et (éventuellement) relancer =====
|
||||
while (running > 0) { // tant qu'il reste des enfants actifs
|
||||
int status = 0;
|
||||
pid_t pid = wait(&status); // attendre qu'UN enfant se termine
|
||||
if (pid < 0) { // erreur (souvent EINTR). On simplifie : on réessaie.
|
||||
if (errno == EINTR){
|
||||
continue;
|
||||
}
|
||||
perror("wait");
|
||||
break;
|
||||
}
|
||||
|
||||
// Retirer ce PID du tableau des actifs (libérer sa case)
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (slots[i] == pid) { // on a trouvé la case de cet enfant
|
||||
slots[i] = 0; // on marque la case vide
|
||||
break;
|
||||
}
|
||||
}
|
||||
running--; // un enfant en moins
|
||||
|
||||
// ===== Q4 : si l'enfant s'est terminé à cause d'un SIGNAL =====
|
||||
if (WIFSIGNALED(status)) {
|
||||
stop = 1; // ne plus lancer de nouveaux enfants
|
||||
// D'abord demander gentiment aux autres de s'arrêter
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (slots[i] > 0) kill(slots[i], SIGTERM);
|
||||
}
|
||||
usleep(100000); // petite pause (100 ms)
|
||||
// Puis forcer l'arrêt si certains sont encore vivants
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (slots[i] > 0) kill(slots[i], SIGKILL);
|
||||
}
|
||||
// on n'ajoute PAS de relance ici (stop=1)
|
||||
}
|
||||
|
||||
// ===== Relancer si : pas d'arrêt global ET il reste des arguments à lancer =====
|
||||
if (!stop && next < argc) {
|
||||
pid_t npid = fork(); // crée un nouvel enfant
|
||||
if (npid == 0) { // dans le nouvel enfant
|
||||
execlp(prog, prog, argv[next], NULL); // lance "prog arg"
|
||||
_exit(127); // si exec échoue
|
||||
}
|
||||
if (npid < 0) { // fork a échoué
|
||||
perror("fork");
|
||||
stop = 1; // arrêter les relances
|
||||
} else {
|
||||
// ranger ce nouveau PID dans une case libre
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (slots[i] == 0) { slots[i] = npid; break; }
|
||||
}
|
||||
running++; // un enfant de plus en cours
|
||||
next++; // passera à l'argument suivant lors de la prochaine relance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(slots); // libérer la mémoire
|
||||
if (stop) return 1; // échec
|
||||
return 0; // succès
|
||||
}
|
||||
BIN
TP_SCR3.1/TP_SIGNAUX/rebours
Executable file
BIN
TP_SCR3.1/TP_SIGNAUX/rebours
Executable file
Binary file not shown.
19
TP_SCR3.1/TP_SIGNAUX/rebours.c
Normal file
19
TP_SCR3.1/TP_SIGNAUX/rebours.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
assert(argc == 2);
|
||||
|
||||
int value = strtol(argv[1], NULL, 0);
|
||||
pid_t p = getpid();
|
||||
printf("%d: debut\n",p);
|
||||
for(int i = value; i>0; i--){
|
||||
printf("%d: %d\n",p,i);
|
||||
sleep(1);
|
||||
}
|
||||
printf("%d: fin\n",p);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
BIN
TP_SCR3.1/TP_Threads/a.out
Executable file
BIN
TP_SCR3.1/TP_Threads/a.out
Executable file
Binary file not shown.
49
TP_SCR3.1/TP_Threads/document-reponse-tp-thread-yolou.c
Normal file
49
TP_SCR3.1/TP_Threads/document-reponse-tp-thread-yolou.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define NUM_THREADS 16
|
||||
|
||||
void *thread(void *thread_id) {
|
||||
long id = ((long ) thread_id);
|
||||
printf("Hello from thread %ld\n", id);
|
||||
|
||||
return (void*)(2*id);
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t threads[NUM_THREADS];
|
||||
int t[NUM_THREADS];
|
||||
long res;
|
||||
for (long i = 0; i < NUM_THREADS; i++){
|
||||
// t[i] = i;
|
||||
assert( pthread_create(&threads[i], NULL, thread, (void*)i) == 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_THREADS; i++){
|
||||
assert( pthread_join(threads[i],(void *)&res) == 0);
|
||||
printf("%ld\n",res);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// 1.L'execution est-elle correcte ?
|
||||
// Non la version est fause
|
||||
/*On voit parfois des IDS faux/repetés selon les exécutions.
|
||||
|
||||
2. Si ce n'est pas le cas, expliquez pourquoi
|
||||
|
||||
Probleme :
|
||||
(Parce qu'on passe l'adresse d'une variable partagée (&i) qui change pendant la creation des threads.
|
||||
Les threads lisent la meme adresse, pas uenc opie de la valeur -> condition de course + duree de vie/visibilité non garanties)
|
||||
&i est l'adresse de la meme variable i de la bouche (une seule variable, qui change de valeur).
|
||||
Les threads démarrent en parrallèle et lisent tous la meme adresse.h
|
||||
Comme i continue de s'incrementer, le contenu vu par les threads depends du timing -> plusieurs threads peuvent lire la meme valeur, ou tous lire la valeur finale(16);
|
||||
Resultat : sorties incorrects / pas vraiment deterministes(certains IDs manquent, d'autres répétes).*/
|
||||
|
||||
|
||||
// Exercie 2 :
|
||||
|
||||
29
TP_SCR3.1/TP_Threads/exo2somme.c
Normal file
29
TP_SCR3.1/TP_Threads/exo2somme.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
|
||||
|
||||
if(argc != 3) {
|
||||
|
||||
fprintf(stderr, "Usage :%s <max> <n>\n",argv[0]);
|
||||
return 1;
|
||||
|
||||
|
||||
}
|
||||
long N = strtol(argv[1], NULL,0);
|
||||
long M = strtol(argv[2], NULL,0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
BIN
TP_SCR3.1/TP_Tubes/a.out
Executable file
BIN
TP_SCR3.1/TP_Tubes/a.out
Executable file
Binary file not shown.
72
TP_SCR3.1/TP_Tubes/ex1.c
Normal file
72
TP_SCR3.1/TP_Tubes/ex1.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int main(void) {
|
||||
int p[2]; // tube : p[0] lecture, p[1] écriture
|
||||
pid_t pf1, pf1f1, pf2;
|
||||
|
||||
pipe(p);
|
||||
|
||||
// --- créer Pf1 ---
|
||||
pf1 = fork();
|
||||
if (pf1 == 0) {
|
||||
// --- créer Pf1f1 ---
|
||||
pf1f1 = fork();
|
||||
if (pf1f1 == 0) {
|
||||
// Pf1f1 : lecteur
|
||||
close(p[1]); // ne garde que la lecture
|
||||
while (1) {
|
||||
pid_t v;
|
||||
read(p[0], &v, sizeof(v));
|
||||
int valeur = read(p[0], &v, sizeof(v));
|
||||
printf(" %d received %d\n", (int)getpid(), (int)v);
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
while (1){
|
||||
pause();
|
||||
}
|
||||
}
|
||||
|
||||
// --- créer Pf2 ---
|
||||
pf2 = fork();
|
||||
if (pf2 == 0) {
|
||||
//Pf2 : écrivain
|
||||
close(p[0]); // ne garde que l’écriture
|
||||
pid_t cmoi = getpid();
|
||||
while (1) {
|
||||
printf("%d sent %d\n", (int)cmoi, (int)cmoi);
|
||||
fflush(stdout);
|
||||
write(p[1], &cmoi, sizeof(cmoi));
|
||||
sleep(3);
|
||||
}
|
||||
}
|
||||
|
||||
//P COMME PAPA
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
while (1){
|
||||
|
||||
pause();
|
||||
|
||||
}
|
||||
printf(valeur);
|
||||
}
|
||||
|
||||
|
||||
// Question 3 : (Envoyez le signal SIGSTOP à Pf2, puis le signal SIGCONT à Pf2)
|
||||
// Pour le premiere comportement quand je stop le processus pf2 avec un kill -STOP 211912 alors mon programme est comme en pause c'est normal car l'action du prcessus de pf1f1 dependait du tube qui relie donc comme il a rien a recevoir il attend.
|
||||
// Puis quand j'utilise SIGCONT le programme se debloque car le pf2 n'est plus gélé donc le pf1f1 peut lire les informations qu'on lui donne.
|
||||
|
||||
//(Envoyez le signal SIGSTOP à Pf1f1, puis le signal SIGCONT à Pf1f1.)
|
||||
//Lors du moment ou j'ai envoyer ce signal le processus pf2 continue d'envoyé ses information au processus pf1f1 sauf que lui comme il est gelé ne reagit pas à sa "requete".
|
||||
// Puis ainsi il rattrape tous ces requetes qui n'a pas pu repondre et du coup comme il est plus rapide que pf2 a la relance il a recup tous les pid possible comme dans le tube il etait rempli de ça donc il a lu les pid qui était la dans le tube.
|
||||
|
||||
|
||||
|
||||
45
TP_SCR3.1/TP_Tubes/ex11.c
Normal file
45
TP_SCR3.1/TP_Tubes/ex11.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
|
||||
|
||||
|
||||
if(argc != 3) {
|
||||
|
||||
fprintf(stderr, "Usage :%s <max> <n>\n",argv[0]);
|
||||
return 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int maxv = atoll(argv[1]);
|
||||
int n = atoi(argv[2]);
|
||||
|
||||
int p[2];
|
||||
pipe(p);
|
||||
|
||||
|
||||
for(int k=0; k<k*n; k++){
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user