Suivez-nous sur X

|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : C - Mémoire tampon en tant que mémoire principale et ChipMemFirst
(Article écrit par Philippe Vautrin et extrait d'Amiga News Tech - novembre 1991)
|
|
Pour illustrer nos nouvelles connaissances sur la gestion de la mémoire
par Exec, je vous propose deux petits programmes C pour le prix d'un seul.
Mémoire Tampon
Le premier programme commence par réserver un tampon mémoire de 16 ko et lui attribue un MemHeader particulier.
Ainsi, on peut user de ce tampon mémoire exactement comme s'il s'agissait de la mémoire principale de
l'ordinateur, à ceci près que seules les fonctions Allocate() et Deallocate() sont utilisables. Ce
programme est interactif, c'est-à-dire que c'est vous qui décidez des opérations à suivre (allocation
ou libération d'un bloc quelconque). Le programme affiche à chaque fois l'état du MemHeader,
les différents MemChunks qui peuvent résulter de la fragmentation du tampon mémoire,
ainsi que l'adresse et la taille des différents blocs alloués.
L'utilisation en est très simple, bien qu'entièrement au clavier. Vous entrez une lettre de commande suivi
d'un nombre x. La lettre peut être A, ce qui demande d'allouer x octets dans le tampon
mémoire, ou bien L, ce qui demander de libérer le bloc numéro x, ou enfin Q, ce qui met fin au programme.
Faites attention à ne bien entrer que des nombres décimaux, aucune vérification particulière n'étant faite à
ce niveau.
Makefile
EXE=Memory
SRC=Memory.c
OBJ=Memory.o
ARG=-b1 -cfist -v -y
LIB=LIB:lc.lib LIB:amiga.lib
LNK=SC SD NOICONS ADDSYM
Memory: $(OBJ)
BLink LIB:c.o $(OBJ) TO $(EXE) LIB $(LIB) $(LNK)
Memory.o: $(SRC)
Lc $(ARG) $(SRC)
|
Listing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#ifdef LATTICE
#include <proto/exec.h>
#endif
#define IsDigit(c) ((c) >= '0' && (c) <= '9')
#define BLOCSIZE 0x4000
UBYTE help[]="\fAn=Allouer n octets, "
"Lx=Libérer bloc n°x, "
"Q=Quitter\n";
void main(void);
void mem_demo(struct MemHeader *mh);
void main(void)
{
struct MemHeader *mh;
struct MemChunk *mc;
if (mh = (struct MemHeader *)AllocMem(sizeof(*mh), MEMF_CLEAR))
{ if (mc = (struct MemChunk *)AllocMem(BLOCSIZE, 0))
{ mh->mh_Node.ln_Type = NT_MEMORY;
mh->mh_Node.ln_Name = "MemDemo.chunck";
mh->mh_First = mc;
mh->mh_Lower = (APTR)mc;
mh->mh_Upper = (APTR)((ULONG)mc + BLOCSIZE);
mh->mh_Free = BLOCSIZE;
mc->mc_Next = NULL;
mc->mc_Bytes = BLOCSIZE;
mem_demo(mh);
FreeMem((APTR)mc, BLOCSIZE);
}
FreeMem((APTR)mh, sizeof(*mh));
}
exit(0);
}
void mem_demo(struct MemHeader *mh)
{
UBYTE cmd[128], c, *ptr, *adr;
ULONG blocs[32], tailles[32], taille;
SHORT bloc, nb_blocs = 0, i;
BOOL fini = FALSE;
struct MemChunk *mc;
for (i = 0; i < 32; i++)
blocs[i] = tailles[i] = -1L;
while (!fini)
{ puts(help);
printf("MemHeader :");
printf(" Lower=$%08lx, Upper=$%08lx, Free=$%08lx\n\n",
mh->mh_Lower, mh->mh_Upper, mh->mh_Free);
for (i = 0, mc = mh->mh_First; mc; mc = mc->mc_Next)
printf("MemChunk %2d, Next=$%08lx, Bytes=$%08lx\n",
i++, mc->mc_Next, mc->mc_Bytes);
printf("\n");
for (i = 0; i < nb_blocs; i++)
printf("Bloc %2d, adresse: $%08lx, taille: $%08lx\n",
i, blocs[i], tailles[i]);
printf("\n[An|Lx|Q] > ");
gets(ptr = cmd);
while (c = *ptr++)
{ switch (c | 0x20)
{ case 'q': /* Quitter */
fini = TRUE;
break;
case 'a': /* Allouer */
c = *ptr++;
while (!IsDigit(c)) c = *ptr++;
taille = c - '0';
c = *ptr++;
while (IsDigit(c))
{ taille = (taille * 10) + (c - '0');
c = *ptr++;
}
*ptr = '\0';
if (nb_blocs < 32)
{ if (taille)
{ adr = Allocate(mh, taille);
if (adr)
{ printf("Allocation de %ld octets\n", taille);
blocs[nb_blocs] = (ULONG)adr;
tailles[nb_blocs] = taille;
nb_blocs++;
}
else puts("L'allocation a échoué !");
}
else puts("Taille incorrecte.");
}
else puts("Nombre maximum de bloc atteint.");
break;
case 'l': /* Libérer */
case 'f':
c = *ptr++;
while (!IsDigit(c)) c = *ptr++;
bloc = c - '0';
c = *ptr++;
while (IsDigit(c))
{ bloc = (bloc * 10) + (c - '0');
c = *ptr++;
}
*ptr = '\0';
if (bloc < nb_blocs)
{ if (blocs[bloc] != -1L)
{ printf("Libération du bloc n°%ld\n\n", bloc);
Deallocate(mh, (APTR)blocs[bloc], tailles[bloc]);
for (i = bloc; i < 32; i++)
{ blocs[i] = blocs[i+1];
tailles[i] = tailles[i+1];
}
--nb_blocs;
}
else puts("Bloc non réservé.");
}
else puts("Numéro de bloc invalide.");
break;
}
}
}
}
|
ChipMemFirst
Ce tout petit programme est un petit truc pour vous permettre de modifier la priorité d'allocation de
la mémoire Chip. Il se contente de changer la priorité de la liste Chip dans la structure ExecBase.
Ainsi, et sous réserve qu'il y en ait suffisamment, ce sera en priorité de la mémoire Chip qu'AllocMem()
et consoeurs alloueront. Cela peut être utile par exemple pour charger une ancienne démo qui refuse
de tourner correctement avec une extension de mémoire.
Par défaut, la nouvelle priorité est de 10, ce qui devrait être amplement suffisant dans la plupart
des cas (Exec l'initialise à -10, la mémoire Fast étant à 0). Mais il peut arriver que certaines extensions,
notamment 32 bits sur les cartes 68030, aient des priorités supérieures. C'est pourquoi il est possible
de préciser en paramètre sur la ligne de commande, la nouvelle priorité à appliquer à la mémoire Chip.
Makefile
EXE=ChipMemFirst
SRC=ChipMemFirst.c
OBJ=ChipMemFirst.o
ARG=-b1 -cfist -v -y
LIB=LIB:lc.lib LIB:amiga.lib
LNK=SC SD NOICONS NODEBUG
ChipMemFirst: $(OBJ)
BLink LIB:c.o $(OBJ) TO $(EXE) LIB $(LIB) $(LNK)
ChipMemFirst.o: $(SRC)
Lc $(ARG) $(SRC)
|
Listing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#ifdef LATTICE
#include <proto/exec.h>
#endif
extern struct ExecBase *SysBase;
void main(int argc, char **argv)
{
int newpri = 25;
struct MemHeader *mh;
if (argc > 1)
newpri = atoi(argv[1]);
Disable();
if (mh = FindName(&SysBase->MemList, "Chip Memory"))
{ Remove((struct Node *)mh);
mh->mh_Node.ln_Pri = newpri;
Enqueue(&SysBase->MemList, (struct Node *)mh);
}
Enable();
}
|
Mise à jour de mai 2025 : une archive contenant le listing adapté à vbcc, et avec l'exécutable
compilé par vbcc, a été réalisée par Yann-Gaël Guéhéneuc et est disponible sur
obligement.free.fr/files/antbufferandchipmemory.lha.
|