FreeRTOS un sistema operativo in tempo reale gratuito e open source originariamente sviluppato da Real Time Engineers Ltd.
Nel 2017, il progetto e il suo team di sviluppatori sono stati acquisiti da Amazon. È stata inoltre creata una versione specifica di FreeRTOS chiamata Amazon FreeRTOS, che include una serie di librerie che facilitano l’integrazione con il cloud Amazon AWS.
È stato portato su oltre 40 architetture diverse e 15 catene di build . Nel 2019 è stato scaricato oltre 185.500 volte.
Il suo design è volutamente minimalista per poter essere installato su piccoli impianti. L’immagine binaria del core pesa tra 4 KB e 9 KB (4,3 KB compilati su ARM7). Il kit minimale ha solo poche funzioni per gestire le attività e la memoria. Inoltre, sono implementate code , semafori e mutex .
Il kernel di versione 7.3.0 è composto di soli cinque file codificati in linguaggio C . Le sezioni in Assembler consentono di garantire la compatibilità di FreeRTOS con le diverse architetture hardware.
È possibile eseguire un numero illimitato di attività contemporaneamente e senza vincoli.
Architettura
FreeRTOS è stato progettato per essere molto leggero, da 4KiB a 9kiB per una tipica immagine binaria del kernel RTOS. Il kernel si compone di soli tre file sorgenti scritti in linguaggio C .
Il pianificatore
Lo scopo principale della pianificazione delle attività è decidere quale delle attività che sono nello stato “pronto” da eseguire. Per effettuare questa scelta, lo scheduler FreeRTOS si basa esclusivamente sulla priorità dei task.
I task in FreeRTOS sono assegnati alla loro creazione, un livello di priorità rappresentato da un numero intero. Il livello più basso è zero e deve essere strettamente riservato per l’attività inattiva . L’utente ha la possibilità di sovrascrivere questo livello con una priorità personalizzata modificando la costante : tskIDLE_PRIORITY . Il numero massimo di livelli di priorità è definito dalla costante: tskMAX_PRIORITIES . Diverse attività possono appartenere allo stesso livello di priorità.
In FreeRTOS non esiste un meccanismo di gestione automatica delle priorità. La priorità di un’attività può essere modificata solo su esplicita richiesta dello sviluppatore.
Le attività sono semplici funzioni che di solito vengono eseguite in un ciclo infinito e seguono la seguente struttura generica:
void vATaskFunction( void *pvParameters )
{
for( ;; )
{
-- Ajouter le code de votre tâche ici --
}
}
Nel caso di un microcontrollore con un solo core, ci sarà in ogni momento un solo task in esecuzione. Lo scheduler assicurerà sempre che l’attività con la priorità più alta che può essere eseguita sia selezionata per entrare nello stato di esecuzione. Se due attività condividono lo stesso livello di priorità ed entrambe sono in grado di essere eseguite, le due attività verranno eseguite alternativamente rispetto alle risvegli dello scheduler ( round robin ).
Per scegliere l’attività da eseguire, lo scheduler stesso deve eseguire e anticipare l’attività in stato di esecuzione. Al fine di garantire il risveglio dello scheduler, FreeRTOS definisce un interrupt periodico chiamato “tick interrupt”. Questo interrupt viene eseguito all’infinito a una certa frequenza definita nel file FreeRTOSConfig.h dalla costante:
configTICK_RATE_HZ /* Fréquence d’exécution de la "tick interrupt" en Hz. */
Questa costante descrive quindi il periodo di tempo assegnato al minimo per ogni attività o spiegato diversamente, l’intervallo che separa due risvegli dello scheduler.
Come descritto in questa sezione, FreeRTOS è quindi un RTOS che utilizza la pianificazione preventiva per gestire le attività. Tuttavia, può anche utilizzare facoltativamente (se gli viene data la direttiva) la pianificazione cooperativa . In questa modalità di pianificazione, si verifica una modifica del contesto di esecuzione solo se l’attività in esecuzione consente esplicitamente l’esecuzione di un’altra attività (ad esempio chiamando un Yield()) o entrando in uno stato di blocco. I compiti quindi non sono mai preceduti. Questa modalità di schedulazione semplifica notevolmente la gestione delle attività, purtroppo può portare a un sistema meno efficiente e meno sicuro.
FreeRTOS può anche utilizzare la pianificazione ibrida, utilizzando la pianificazione preventiva e la pianificazione cooperativa. In questa modalità può avvenire anche un cambio di contesto di esecuzione in caso di interruzione.
Fame
In FreeRTOS, l’attività di priorità più alta pronta per l’esecuzione sarà sempre selezionata dallo scheduler. Questo può portare a una situazione di carestia . Questo perché se l’attività con priorità più alta non viene mai interrotta , tutte le attività con priorità inferiore non verranno mai eseguite. FreeRTOS non implementa alcun meccanismo automatico per prevenire il fenomeno della fame. Lo sviluppatore deve assicurarsi che non vi siano attività che monopolizzano tutto il tempo di esecuzione del microcontrollore. Per questo può collocare eventi che interromperanno il compito di priorità più alta per un determinato tempo o fino al verificarsi di un altro evento e lasciando così il campo libero per l’esecuzione di compiti di priorità inferiore.
Per evitare la fame, lo sviluppatore può utilizzare la pianificazione della velocità monotona (RMS). È una tecnica di assegnazione delle priorità che assegna a ciascuna attività una priorità univoca in base alla sua frequenza di esecuzione. La priorità più alta è assegnata al task con la frequenza di esecuzione più alta e la priorità più bassa è assegnata al task con la frequenza più bassa. La schedulazione a ritmi monotoni consente di massimizzare la schedulabilità dei compiti, ma ciò rimane difficile da realizzare a causa della natura dei compiti che non sono completamente periodici.
Il compito inattivo
Un microcontrollore dovrebbe sempre avere qualcosa da fare. In altre parole, deve sempre esserci un’attività in esecuzione. FreeRTOS gestisce questa situazione definendo il task Idle che viene creato all’avvio dello scheduler. A questa attività viene assegnata la priorità kernel più bassa. Nonostante ciò, l’attività inattiva può avere diverse funzioni da eseguire, tra cui:
- Libera lo spazio occupato da un’attività eliminata.
- Mettere il microcontrollore in standby per risparmiare energia del sistema quando non è in esecuzione alcuna attività dell’applicazione.
- Misurare il tasso di utilizzo del processore .
Descrizione dei compiti
In FreeRTOS, ogni task è descritto da un TCB (Task control Block) che contiene tutte le informazioni necessarie per specificare e rappresentare un task.
| Variabili | Descrizione |
|---|---|
| pxTopOfStack | Puntatore all’ultimo elemento in cima alla pila |
| xGenericListItem | Membro (xListItem) dell’elenco utilizzato per posizionare il TCB in un elenco di stati (Pronto, bloccato o sospeso). |
| xEventListItem | Elemento dell’elenco (xListItem) utilizzato per posizionare il TCB in un elenco di eventi. |
| uxPriority | Priorità dell’attività |
| pxStack | Puntatore all’inizio dello stack del processo |
| pxEndOfStack | Puntatore alla fine dello stack del processo |
| uxTCBNumber | Dimensione dello stack in numero di variabili |
| pcTaskName | Numero che aumenta ogni volta che viene creato un TCB (utilizzato per il debug) |
| uxBasePriority | L’ultima priorità assegnata all’attività |
| ulRunTimeCounter | Calcola il tempo trascorso dall’attività in uno stato di esecuzione |
| pxTaskTag | Consente di aggiungere un tag a un’attività. Il Tag viene utilizzato per effettuare Log tramite le uscite analogiche o digitali grazie alla funzione traceSWITCHED_IN(). |
| uxCriticalNesting | Consente di salvare la profondità di annidamento delle sezioni critiche di questa attività. Ogni volta che l’attività entra in una sezione critica, la variabile viene incrementata, viene decrementata non appena l’attività esce da una sezione critica.Questa variabile è necessaria perché è possibile che l’attività restituisca il controllo mentre si trova nella sezione critica. |
Le attività sotto FreeRTOS possono esistere in 5 stati: “cancellato”, “sospeso”, “pronto”, “bloccato” o “in esecuzione”.
In FreeRTOS, non esiste una variabile per specificare in modo esplicito lo stato di un’attività, in cambio FreeRTOS utilizza elenchi di stati. La presenza dell’attività in un tipo di elenco di stato ne determina lo stato (pronto, bloccato o sospeso). Poiché le attività cambiano spesso stato, lo scheduler dovrà solo spostare l’attività (l’elemento (xListItem) appartenente a questa stessa attività) da un elenco di stati a un altro.
Quando si crea un’attività, FreeRTOS crea e compila il TCB corrispondente all’attività, quindi inserisce direttamente l’attività in una “Lista Pronta” (Lista contenente un riferimento a tutte le attività che si trovano nello stato “Pronto”).
FreeRTOS mantiene diversi “Ready List”, esiste un elenco per ogni livello di priorità. Quando si sceglie l’attività successiva da eseguire, lo scheduler analizza le “Liste pronte” dalla priorità più alta a quella più bassa.
Piuttosto che definire esplicitamente uno stato “in esecuzione” o un elenco ad esso associato, il kernel FreeRTOS descrive una variabile “pxCurrentTCB” che identifica il processo in esecuzione. Questa variabile punta al TCB corrispondente al processo che si trova in uno degli ‘Ready list’.
Un’attività può finire nello stato “bloccato” quando si accede a una coda di lettura/scrittura se la coda è vuota/piena. Ogni operazione di accesso alla coda è configurata con un timeout (xTicksToWait).Se questo timeout è 0, l’attività non viene bloccata e l’operazione di accesso alla coda è considerata fallita. Se il timeout non è zero, l’attività passa allo stato ‘bloccato’ fino a quando non si verifica una modifica della coda (ad esempio da un’altra attività). Una volta che l’operazione di accesso alla coda è possibile, l’attività verifica che il suo timeout non sia scaduto e completa correttamente l’operazione.
Un’attività può essere posta volontariamente nello stato “sospeso”, verrà quindi totalmente ignorata dallo scheduler e non consumerà più risorse fino a quando non verrà rimossa dallo stato e rimessa in uno stato “pronto”. .
L’ultimo stato che un’attività può assumere è lo stato “eliminato”, questo stato è necessario perché un’attività eliminata non rilascia le sue risorse istantaneamente. Una volta nello stato “cancellato”, l’attività viene ignorata dallo scheduler e un’altra attività denominata “IDLE” è responsabile della liberazione delle risorse allocate dalle attività che si trovano nello stato “cancellato”.
Il task “IDLE” viene creato all’avvio dello scheduler e gli viene assegnata la priorità più bassa possibile che porta a un rilascio ritardato delle risorse quando nessun altro task è in esecuzione.
Strutture dati FreeRTOS
Le liste
Le liste sono le strutture dati più utilizzate in FreeRTOS. Vengono utilizzati per l’organizzazione e la pianificazione delle attività, nonché per l’implementazione delle code.
FreeRTOS definisce diverse strutture per rappresentare le liste:
- La struttura xLIST rappresenta l’intestazione degli elenchi che vengono creati e utilizzati dallo scheduler. Ad esempio, gli elenchi di attività pronte (un elenco per livello di priorità), l’elenco di attività bloccate, ecc. Questa struttura contiene in qualche modo le altre strutture di lista usate da FreeRTOS.
La struttura xLIST è definita come segue:
typedef struct xLIST
{
volatile unsigned portBASE_TYPE uxNumberOfItems; /* Le nombre d'éléments dans cette liste. */
volatile xListItem * pxIndex; /* Pointeur utilisé pour parcourir cette liste,
il pointe successivement sur les éléments (xLIST_ITEM)
contenus dans cette liste. */
volatile xMiniListItem xListEnd; /* Élément marquant la fin de cette liste.
Elle contient pour cela la valeur maximale de la variable
xItemValue dans la liste. */
} xList;
- La struttura xLIST_ITEM rappresenta gli elementi di una lista (di Tipo xLIST). Ogni elemento di un elenco è collegato a un compito e le diverse variabili della struttura xLIST_ITEM vengono utilizzate per organizzare i compiti e collegarli insieme per formare un elenco doppiamente collegato.
La struttura xLIST_ITEM è definita come segue:
struct xLIST_ITEM
{
portTickType xItemValue; /* Une valeur attribuée à cet élément,
cette valeur est utilisée afin de trier
la liste (de type (xLIST) contenant cet élément (xLIST_ITEM))
dans un ordre décroissant. */
volatile struct xLIST_ITEM * pxNext; /* Pointeur vers le prochain élément (xLIST_ITEM)
dans la liste (xLIST). */
volatile struct xLIST_ITEM * pxPrevious; /* Pointeur vers le précédent élément (xLIST_ITEM)
dans la liste (xLIST). */
void * pvOwner; /* Pointeur vers l'objet contenant cet élément,
cet objet est, dans la plupart des cas, le TCB d'une tâche. */
void * pvContainer; /* Pointeur vers la liste (xLIST) dans laquelle cet
élément est contenu. */
};
- La struttura XMiniListItem è una versione ridotta di XLIST_ITEM . Non ha le variabili pvOwner e pvContainer . Rappresenta un elemento che segna la fine di questo elenco.

Le linee
Le code sono i principali meccanismi che consentono alle attività di comunicare e sincronizzarsi tra loro.
La struttura di base di una coda è descritta come segue:
typedef struct QueueDefinition
{
signed char *pcHead; /* Pointeur sur l'octet de début de la file
en mémoire */
signed char *pcTail; /* Pointeur sur l'octet de fin de la file
en mémoire (un octet de plus que nécessaire,
car utilisé comme un marqueur de fin). */
signed char *pcWriteTo; /* Pointeur sur le prochain [[octet]] libre dans la
file. */
signed char *pcReadFrom; /* Pointeur sur le dernier octet lu de la file. */
xList xTasksWaitingToSend; /* Liste des tâches (ordonnées par niveau de priorités)
qui sont bloquées en attente d’écriture
sur la file. */
xList xTasksWaitingToReceive; /* Liste des tâches (ordonnées par niveau de priorités)
qui sont bloquées en attente de lecture depuis la
file .*/
volatile unsigned portBASE_TYPE uxMessagesWaiting; /* Nombre d'éléments actuellement contenus
dans la file. */
unsigned portBASE_TYPE uxLength; /* Taille de la file définit comme le nombre
d'éléments maximum qu'elle peut contenir
et non le nombre d'octets. */
unsigned portBASE_TYPE uxItemSize; /* Taille de chaque élément (en octet) que
la file pourra contenir. */
} xQUEUE;
Una coda contiene un numero finito di elementi di dimensione fissa. La dimensione fisica di una coda è determinata dal numero massimo di elementi che può contenere ( uxLength ) moltiplicato per la dimensione in byte di ciascun elemento ( uxItemSize ).
In FreeRTOS, la scrittura o l’invio di dati a una coda viene eseguita copiando byte per byte e indipendentemente dal tipo perché la durata dell’elemento salvato è spesso inferiore alla durata della coda. . Come l’operazione di scrittura, anche la lettura o ricezione dei dati viene effettuata copiando byte per byte i dati che verranno cancellati dalla coda.
Le code sono oggetti indipendenti, non c’è assegnazione o appartenenza a un’attività. Sono le strutture che consentono ai compiti di comunicare tra loro. Pertanto, possono avere più attività di lettura e scrittura contemporaneamente.
Le operazioni di scrittura o lettura sulle code possono essere bloccanti o non bloccanti. Le operazioni non bloccanti restituiscono direttamente alla coda lo stato di esito positivo o negativo . Le operazioni di blocco sono configurate con un timeout che consente loro di bloccarsi e che determina il tempo massimo durante il quale possono rimanere in questo stato.
Gestione delle risorse
FreeRTOS utilizza le code come mezzo di comunicazione tra le attività. Tuttavia, le code gestiscono anche la sincronizzazione e la competizione tra le attività. Pertanto, questa struttura è l’elemento base per la gestione delle risorse in FreeRTOS.
FreeRTOS sincronizza le attività utilizzando principalmente due meccanismi: Semafori e Mutex .
Semafori
Schema di base dell’utilizzo di un semaforo binario
FreeRTOS consente la creazione e l’utilizzo di Semafori con più elementi. I semafori sono implementati sotto forma di coda in modo tale che il numero di elementi del semaforo rappresenti il numero massimo di elementi che la coda può contenere. La coda che rappresenta il semaforo non salva alcun dato, si occupa solo di registrare il numero delle sue voci attualmente occupate. La dimensione degli elementi in coda è quindi zero (uxItemSize = 0). Un accesso al Semaforo aumenta o diminuisce solo il numero di voci occupate nella coda e non viene eseguita alcuna copia dell’elemento.
L’API offerta da FreeRTOS per la gestione dei semafori fa la differenza tra semafori ad elementi N e semafori binari. I semafori binari possono essere visti come code che possono contenere solo un elemento. Un semaforo binario può quindi essere preso solo una volta prima che diventi indisponibile a differenza di un semaforo con n elementi che può essere preso più volte il che permette, ad esempio, di definire un numero di risorse disponibili o di contare il numero di eventi che devono ancora essere eseguito.
Mutex
Schema dell’uso di un Mutex per garantire la mutua esclusione
Un Mutex viene utilizzato per proteggere una risorsa condivisa.
L’implementazione di Mutex in FreeRTOS è simile a quella dei semafori binari (sotto forma di coda) tranne per il fatto che l’attività che prende il Mutex deve obbligatoriamente restituirlo. Questo può essere visto come l’associazione di un token con una risorsa, un’attività prende il token e utilizza la risorsa, quindi restituisce il token alla fine, allo stesso tempo nessun altro token aggiuntivo può essere associato all’attività.
Un’altra importante differenza tra Mutex e Binary Semaphores in FreeRTOS è il sistema di ereditarietà prioritaria. Quando più task richiedono di prendere un Mutex, la priorità del titolare del Mutex viene momentaneamente impostata sul valore della priorità più alta tra i task in attesa di rilascio. Questa tecnica ha l’effetto di prevenire fenomeni a rischio di inversione di priorità anche se ciò non garantisce una sicurezza infallibile di fronte a tali fenomeni.
Gestione delle interruzioni
Un interrupt è un meccanismo puramente hardware che viene implementato e avviato da quest’ultimo. FreeRTOS fornisce solo metodi per la gestione degli interrupt e può anche avviare gli interrupt chiamando un’istruzione hardware.
FreeRTOS non impone agli sviluppatori alcuna strategia specifica per la gestione degli interrupt, ma offre diversi mezzi affinché la strategia scelta possa essere implementata e mantenuta facilmente.
Le routine di interrupt (ISR) sono funzioni eseguite dal microcontrollore stesso e che non possono essere gestite da FreeRTOS, il che può causare alcuni problemi. Per questi motivi, le routine di interrupt non possono utilizzare le normali funzioni API di FreeRTOS che possono essere utilizzate da qualsiasi altra attività di base. Tuttavia, FreeRTOS definisce un gruppo di funzioni appositamente progettate per gli ISR, ad esempio un ISR utilizzerà la funzione xSemaphoreGiveFromISR () anziché xSemaphoreGive () , allo stesso modo utilizzerà la funzione xQueueReceiveFromISR () anziché xQueueReceive () .
Gestione degli interrupt hardware da FreeRTOS in base ai loro livelli di priorità
Per specificare una politica di gestione degli interrupt e per gestire l’accesso alle funzioni del kernel specifiche di ISR, FreeRTOS definisce delle costanti nel file di configurazione di FreeRTOSConfig.h :
- configKERNEL_INTERRUPT_PRIORITY : Definisce il livello di priorità dell’interrupt temporale ( ang . Tick interrupt) che è un interrupt periodico utilizzato per avviare lo scheduler ad ogni intervallo di tempo.
- configMAX_SYSCALL_INTERRUPT_PRIORITY : definisce il livello di priorità più alto per il quale possono essere utilizzate le funzioni specifiche di ISR di FreeRTOS.
La definizione di queste due costanti consente di specificare una politica di gestione della PSR in base al loro livello di priorità:
- un ISR con un livello di priorità compreso tra configKERNEL_INTERRUPT_PRIORITY e configMAX_SYSCALL_INTERRUPT_PRIORITY potrà utilizzare le funzioni dell’API specifiche per gli ISR, potrà prevalere su un task, ma non sul kernel né su un task che esegue una sezione critica. Non può essere anticipato dallo scheduler perché l’interruzione del timer tick ha una priorità inferiore.
- un ISR con un livello di priorità strettamente superiore a configMAX_SYSCALL_INTERRUPT_PRIORITY sarà in grado di anticipare lo scheduler, anche durante l’esecuzione di sezioni di codice critico. In cambio, non avrà più accesso a nessuna delle funzioni dell’API FreeRTOS.
- un ISR che non utilizza nessuna delle funzioni API di FreeRTOS può utilizzare qualsiasi livello di priorità.
La definizione delle due costanti precedenti aggiunge all’ISR anche la particolarità dell’annidamento delle interruzioni ( ang . Interrupt Nesting). L’annidamento degli interrupt è la possibilità che un secondo interrupt si verifichi nello stesso momento in cui un altro interrupt viene elaborato da un ISR. Questo secondo interrupt può precedere il primo se ha una priorità più alta.
Va notato che le priorità degli interrupt sono definite dall’architettura del microcontrollore. Queste sono priorità hardware che non hanno alcuna relazione con le priorità software che possono essere assegnate ai task con FreeRTOS.
Interruzioni differite
Diagramma che descrive l’uso di un interrupt differito
Come specificato in precedenza, gli ISR sono sezioni di codice eseguite dal microcontrollore e non da FreeRTOS. Il che porta a un comportamento imprevisto del kernel. Per questo motivo è necessario ridurre al minimo i tempi di esecuzione di un ISR. Una strategia per ridurre il tempo di esecuzione è utilizzare i semafori binari offerti da FreeRTOS. Un semaforo binario può essere utilizzato per sbloccare un’attività ogni volta che si verifica un particolare interrupt. Così la parte di codice eseguita nell’ISR può essere notevolmente ridotta e la gestione dell’interrupt tornerà in gran parte al compito sbloccato. Avremo così rinviato il processo di interruzione a un compito semplice.
Se l’interrupt risulta critico, allora si può definire la priorità del task di gestione degli interrupt in modo da prevalere sempre sugli altri task del sistema.
Sospensione delle interruzioni
FreeRTOS permette di proteggere sezioni di codice appartenenti a un task da qualsiasi cambiamento di contesto, di operazione dello scheduler o anche di un interrupt che viene sollevato; queste porzioni di codice sono chiamate sezioni critiche . L’uso di sezioni critiche può essere efficace nel rispettare l’atomicità di determinate istruzioni. Tuttavia, queste sezioni critiche devono essere utilizzate con cautela poiché durante la loro esecuzione il sistema rimane statico e totalmente inattivo verso altri task critici che verrebbero bloccati oppure verso interrupt che segnalano eventi esterni critici.
Per definire una parte di codice come una sezione critica, è sufficiente racchiuderla tra le due istruzioni di sezione critica di inizio e fine: taskENTER_CRITICAL () e taskEXIT_CRITICAL () .
Gestione della memoria
Il kernel FreeRTOS deve allocare dinamicamente la memoria RAM ogni volta che viene creato un task , una coda o un semaforo . L’utilizzo dei metodi tradizionali Malloc() e Free() è ancora possibile ma può porre alcuni problemi perché non sono deterministici e possono soffrire di memoria troppo frammentata. Pertanto , esistono due metodi che utilizzano gli stessi prototipi in FreeRTOS: pvPortMalloc() e vPortFree() .
Ciascuno di essi è implementato in tre modi differenti descritti nei file Heap_1.c , Heap_2.c e Heap_3.c ma l’utente è libero di definire le proprie funzioni.
La costante configTOTAL_HEAP_SIZE definita nel file di configurazione di FreeRTOSConfig.h
La prima implementazione
Schema esplicativo della prima implementazione dell’allocazione di memoria in FreeRTOS
Questa versione non definisce un metodo per liberare spazio nella memoria RAM.
La memoria è suddivisa in un array di dimensioni configTOTAL_HEAP_SIZE (in byte) denominato “lo stack FreeRtos”.
Quando il kernel ha bisogno di allocare memoria, riserva due spazi liberi per lo stesso compito. Il primo è utilizzato per il TCB mentre il secondo rappresenta la coda. Poiché lo spazio di memoria per le attività non viene mai liberato, lo stack si riempie fino all’esaurimento dello spazio disponibile.
La seconda implementazione
Diagramma esplicativo della seconda implementazione dell’allocazione di memoria in FreeRTOS
Questa rappresentazione differisce dalla prima in quanto dispone di un metodo vPortFree() che libera la memoria allocata per un’attività e può allocarla nuovamente a un’altra attività. La dimensione del blocco di memoria del nuovo task deve essere al massimo uguale alla dimensione del blocco del vecchio task.
La terza implementazione
Questa è solo una ridefinizione di Malloc() e Free() ma dove la sicurezza è stata aumentata sospendendo tutte le attività per la durata dell’operazione sulla memoria.