Commit 57f7062e authored by Joan Besante's avatar Joan Besante
Browse files

new

parent 42d04b93
*.o
.*.o.deps
/memshell
/test_init
CC=gcc
# uncomment to compile in 32bits mode (require gcc-*-multilib packages
# on Debian/Ubuntu)
#HOST32= -m32
CFLAGS+= $(HOST32) -Wall -Werror -std=c99 -g -D_GNU_SOURCE
CFLAGS+= -DDEBUG
# pour tester avec ls
CFLAGS+= -fPIC
LDFLAGS= $(HOST32)
TESTS+=test_init
PROGRAMS=memshell $(TESTS)
.PHONY: clean all test_ls
all: $(PROGRAMS)
for file in $(TESTS);do ./$$file; done
%.o: %.c
$(CC) -c $(CFLAGS) -MMD -MF .$@.deps -o $@ $<
# dépendences des binaires
$(PROGRAMS) libmalloc.so: %: mem.o common.o
-include $(wildcard .*.deps)
# seconde partie du sujet
libmalloc.so: malloc_stub.o
$(CC) -shared -Wl,-soname,$@ $^ -o $@
test_ls: libmalloc.so
LD_PRELOAD=./libmalloc.so ls
# nettoyage
clean:
$(RM) *.o $(PROGRAMS) libmalloc.so .*.deps
Ce package contient :
- un petit programme de test interactif de l'allocateur qui devra être implémenté dans mem.c : memshell
- un petit programme contenant un test simple de l'initialisation de l'allocateur qui devra être implémenté dans mem.c : test_init
- un Makefile vous permettant de compiler tout ces petits programmes et de tester votre allocateur avec une appli réelle (make test_ls)
ATTENTION: sans implémentation correcte du début de l'allocateur, test_init boucle indéfiniment.
#include "mem.h"
#include "common.h"
#include <assert.h>
#include <stdio.h>
/* Size of the managed memory
*
* For this to work, we expect a call to
* mem_init(get_memory_adr(), get_memory_size())
*/
#ifndef MEMORY_SIZE
#define MEMORY_SIZE 8192
#endif
static char memory[MEMORY_SIZE];
void *get_memory_adr() {
return memory;
}
size_t get_memory_size() {
return MEMORY_SIZE;
}
void *alloc_max(size_t estimate) {
void *result;
static size_t last = 0;
while ((result = mem_alloc(estimate)) == NULL) {
estimate--;
if(!estimate) {
fprintf(stderr, "Allocation failed\n");
return NULL;
}
}
debug("Alloced %zu bytes at %p\n", estimate, result);
if (last) {
// Idempotence test
assert(estimate == last);
} else
last = estimate;
return result;
}
#ifndef __COMMON_H__
#define __COMMON_H__
#include <stdlib.h>
#ifdef DEBUG
# include <stdio.h>
# define debug(...) ((void)fprintf(stderr, __VA_ARGS__))
#else
# define debug(...) ((void)0)
#endif
/* function to retrieve info about the globally allocated memory zone */
void *get_memory_adr();
size_t get_memory_size();
/* function to try to allocate as much as memory as possible */
void *alloc_max(size_t estimate);
#endif
#include "mem.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
static __thread int in_lib=0;
#define dprintf(args...) \
do { \
if (!in_lib) { \
in_lib=1; \
fprintf(stderr, args); \
in_lib=0; \
} \
} while (0)
static
void init() {
static int first=1;
if (first) {
mem_init(get_memory_adr(), get_memory_size());
first = 0;
}
}
void *malloc(size_t s) {
void *result;
init();
dprintf("Allocation de %lu octets...", (unsigned long) s);
result = mem_alloc(s);
if (!result)
dprintf(" Alloc FAILED !!");
else
dprintf(" %lx\n", (unsigned long) result);
return result;
}
void *calloc(size_t count, size_t size) {
int i;
char *p;
size_t s = count*size;
init();
dprintf("Allocation de %zu octets\n", s);
p = mem_alloc(s);
if (!p)
dprintf(" Alloc FAILED !!");
if (p)
for (i=0; i<s; i++)
p[i] = 0;
return p;
}
void *realloc(void *ptr, size_t size) {
size_t s;
char *result;
init();
dprintf("Reallocation de la zone en %lx\n", (unsigned long) ptr);
if (!ptr) {
dprintf(" Realloc of NULL pointer\n");
return mem_alloc(size);
}
if (mem_get_size(ptr) >= size) {
dprintf(" Useless realloc\n");
return ptr;
}
result = mem_alloc(size);
if (!result) {
dprintf(" Realloc FAILED\n");
return NULL;
}
for (s = 0; s<mem_get_size(ptr); s++)
result[s] = ((char *) ptr)[s];
mem_free(ptr);
dprintf(" Realloc ok\n");
return result;
}
void free(void *ptr) {
init();
if (ptr) {
dprintf("Liberation de la zone en %lx\n", (unsigned long) ptr);
mem_free(ptr);
} else {
dprintf("Liberation de la zone NULL\n");
}
}
#ifndef __MALLOC_STUB_H__
#define __MALLOC_STUB_H__
#include <stdlib.h>
void *malloc(size_t s);
void *calloc(size_t count, size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
#endif
/* On inclut l'interface publique */
#include "mem.h"
#include <assert.h>
#include <stddef.h>
#include <string.h>
/* Définition de l'alignement recherché
* Avec gcc, on peut utiliser __BIGGEST_ALIGNMENT__
* sinon, on utilise 16 qui conviendra aux plateformes qu'on cible
*/
#ifdef __BIGGEST_ALIGNMENT__
#define ALIGNMENT __BIGGEST_ALIGNMENT__
#else
#define ALIGNMENT 16
#endif
/* structure placée au début de la zone de l'allocateur
Elle contient toutes les variables globales nécessaires au
fonctionnement de l'allocateur
Elle peut bien évidemment être complétée
*/
struct allocator_header {
size_t memory_size;
mem_fit_function_t *fit;
};
/* La seule variable globale autorisée
* On trouve à cette adresse le début de la zone à gérer
* (et une structure 'struct allocator_header)
*/
static void* memory_addr;
static inline void *get_system_memory_addr() {
return memory_addr;
}
static inline struct allocator_header *get_header() {
struct allocator_header *h;
h = get_system_memory_addr();
return h;
}
static inline size_t get_system_memory_size() {
return get_header()->memory_size;
}
struct fb {
size_t size;
struct fb* next;
/* ... */
};
void mem_init(void* mem, size_t taille)
{
memory_addr = mem;
*(size_t*)memory_addr = taille;
/* On vérifie qu'on a bien enregistré les infos et qu'on
* sera capable de les récupérer par la suite
*/
assert(mem == get_system_memory_addr());
assert(taille == get_system_memory_size());
/* ... */
mem_fit(&mem_fit_first);
}
void mem_show(void (*print)(void *, size_t, int)) {
/* ... */
while (/* ... */ 0) {
/* ... */
print(/* ... */NULL, /* ... */0, /* ... */0);
/* ... */
}
}
void mem_fit(mem_fit_function_t *f) {
get_header()->fit = f;
}
void *mem_alloc(size_t taille) {
/* ... */
__attribute__((unused)) /* juste pour que gcc compile ce squelette avec -Werror */
struct fb *fb=get_header()->fit(/*...*/NULL, /*...*/0);
/* ... */
return NULL;
}
void mem_free(void* mem) {
}
struct fb* mem_fit_first(struct fb *list, size_t size) {
return NULL;
}
/* Fonction à faire dans un second temps
* - utilisée par realloc() dans malloc_stub.c
* - nécessaire pour remplacer l'allocateur de la libc
* - donc nécessaire pour 'make test_ls'
* Lire malloc_stub.c pour comprendre son utilisation
* (ou en discuter avec l'enseignant)
*/
size_t mem_get_size(void *zone) {
/* zone est une adresse qui a été retournée par mem_alloc() */
/* la valeur retournée doit être la taille maximale que
* l'utilisateur peut utiliser dans cette zone */
return 0;
}
/* Fonctions facultatives
* autres stratégies d'allocation
*/
struct fb* mem_fit_best(struct fb *list, size_t size) {
return NULL;
}
struct fb* mem_fit_worst(struct fb *list, size_t size) {
return NULL;
}
#ifndef __MEM_H
#define __MEM_H
#include <stddef.h>
struct fb;
/* fonctions principales de l'allocateur */
void mem_init(void* mem, size_t taille);
void* mem_alloc(size_t size);
void mem_free(void *ptr);
void* mem_realloc(void *old, size_t new_size);
/* Itération sur le contenu de l'allocateur */
/* nécessaire pour le mem_shell */
void mem_show(void (*print)(void *adr, size_t size, int free));
/* Choix de la stratégie et strategies usuelles */
/* Si vous avez le temps... */
typedef struct fb* (mem_fit_function_t)(struct fb*, size_t);
void mem_fit(mem_fit_function_t*);
mem_fit_function_t mem_fit_first;
mem_fit_function_t mem_fit_worst;
mem_fit_function_t mem_fit_best;
#endif
#include "mem.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#define TAILLE_BUFFER 128
void aide()
{
fprintf(stderr,"Aide :\n");
fprintf(stderr,"Saisir l'une des commandes suivantes\n");
fprintf(stderr,"\n");
fprintf(stderr,"a taille : allouer un bloc de la taille souhaitee\n");
fprintf(stderr,"l adresse : librer un bloc alloue precedemment\n");
fprintf(stderr,"i : afficher la liste des emplacements memoire "
"inocupes\n");
fprintf(stderr,"o : afficher la liste des emplacements memoire "
"occupes\n");
fprintf(stderr,"M : afficher la liste de tous les emplacements "
"memoire (libres et occupes)\n");
fprintf(stderr,"m : afficher le dump de la memoire\n");
fprintf(stderr,"h : afficher cette aide\n");
fprintf(stderr,"q : quitter ce programme\n");
fprintf(stderr,"\n");
}
void afficher_zone(void *adresse, size_t taille, int free)
{
printf("Zone %s, Adresse : %lu, Taille : %lu\n", free?"libre":"occupee",
adresse - get_memory_adr(), (unsigned long) taille);
}
void afficher_zone_libre(void *adresse, size_t taille, int free)
{
if (free)
afficher_zone(adresse, taille, 1);
}
void afficher_zone_occupee(void *adresse, size_t taille, int free)
{
if (!free)
afficher_zone(adresse, taille, 0);
}
int main()
{
char buffer[TAILLE_BUFFER];
char commande;
char *adresse;
void *ptr;
int offset;
int taille, i;
aide();
mem_init(get_memory_adr(),get_memory_size());
while (1) {
printf("? ");
fflush(stdout);
commande = getchar();
switch (commande) {
case 'a':
scanf ("%d",&taille);
ptr = mem_alloc(taille);
if (ptr == NULL)
printf("Echec de l'allocation\n");
else
printf("Memoire allouee en %d\n", (int) (ptr-get_memory_adr()));
break;
case 'l':
scanf ("%d", &offset);
mem_free(get_memory_adr()+offset);
printf("Memoire liberee\n");
break;
case 'i':
mem_show(afficher_zone_libre);
break;
case 'o':
mem_show(afficher_zone_occupee);
break;
case 'M':
mem_show(afficher_zone);
break;
case 'm':
printf("[ ");
adresse = get_memory_adr();
for (i=0; i<get_memory_size(); i++)
printf("%d ", adresse[i]);
printf("]\n");
break;
case 'h':
aide();
break;
case 'q':
exit(0);
default:
fprintf(stderr,"Commande inconnue !\n");
}
/* vide ce qu'il reste de la ligne dans le buffer d'entree */
fgets(buffer,TAILLE_BUFFER,stdin);
}
return 0;
}
#include "mem.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define NB_TESTS 10
int main(int argc, char *argv[]) {
fprintf(stderr, "Test réalisant de multiples fois une initialisation suivie d'une alloc max.\n"
"Définir DEBUG à la compilation pour avoir une sortie un peu plus verbeuse."
"\n");
for (int i=0; i<NB_TESTS; i++) {
debug("Initializing memory\n");
mem_init(get_memory_adr(), get_memory_size());
alloc_max(get_memory_size());
}
// TEST OK
return 0;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment