flowchart LR
A[Gestor de Memòria] --> B[Molts processos]
B --> C[Ubicats a Memòria]
C --> D[De forma simultània]
D --> E[S'ha de compartir Memòria física]
Unitat 6 · Sistemes Operatius (SO)
Imaginem un sistema operatiu sense cap mecanisme per gestionar la memòria. Quan un programa s’executa, pot executar una instrucció com MOV REG1, 1000, que mou el contingut de la memòria física 1000 a REG1.
En aquesta situació, què passaria si executéssim dos programes simultàniament?
MOV REG1, 1000, i després el segon programa executa MOV REG1, 1000, el contingut de la memòria escrita pel primer programa seria sobreescrit pel segon programa.Una possible solució seria utilitzar memòria secundària i anar fent swapping de la memòria principal a la secundària. Però, això seria molt lent i poc viable.
flowchart LR
A[Gestor de Memòria] --> B[Molts processos]
B --> C[Ubicats a Memòria]
C --> D[De forma simultània]
D --> E[S'ha de compartir Memòria física]
El mapa de memòria d’un procés és una representació lògica de com la memòria està organitzada per a un programa en execució. Normalment conté diferents regions o segments que es creen a partir de la seva execució.
Una zona contigua de memòria amb un punt inicial i una mida definida.

Suposem que tenim un programa que realitza la multiplicació de dues matrius. Aquestes matrius s’introdueixen per teclat en temps d’execució, i el programa no pot determinar la mida de les matrius fins que l’usuari les introdueixi. Per tant, necessitem un model de memòria dinàmic.
Suposem que el programa necessita emmagatzemar dades d’un fitxer que no es coneix prèviament. En aquest cas, el sistema operatiu pot crear noves regions en el mapa de memòria per aquestes dades a mesura que el procés llegeix el fitxer, adaptant-se dinàmicament a la demanda.
A més, els SOs utilitzen biblioteques dinàmiques que impliquen la creació de regions associades a la mateixa i que contenen les diferents seccions de la biblioteca (codi i dades globals). Per exemple, quan carreguem una biblioteca dinàmica comuna, el sistema operatiu pot crear noves regions en el mapa de memòria del procés per al codi executable i les variables globals de la biblioteca.
Els Sistemes Operatius ofereixen un model de memòria dinàmic i necessiten mantenir una taula de regions per cada procés format per un nombre variable de regions que es poden afegir o eliminar durant la seva execució.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int global;
int
main(int argc, char **argv) {
int private;
(void) printf("argc at : 0x%12lX\n", (unsigned long)&argc);
(void) printf("argv at : 0x%12lX\n", (unsigned long)&argv);
(void) printf("private at: 0x%12lX\n", (unsigned long)&private);
(void) printf("global at : 0x%12lX\n", (unsigned long)&global);
(void) printf("main at : 0x%12lX\n", (unsigned long)&main);
return EXIT_SUCCESS;
}void f() {
int stackVar = 42;
printf("stackVar at: 0x%p\n", (void*)&stackVar);
int* heapVar = malloc(4);
printf("Malloced Area Begins at: 0x%p\n", (void*)heapVar);
printf("Malloced Area Ends at: 0x%p\n", (void*)(heapVar + 1));
free(heapVar);
}
void main() {
int mainVar = 0;
printf("Stack Frame of main at: 0x%p\n", (void*)&mainVar);
f();
printf("End of Stack Frame: 0x%p\n", (void*)&mainVar);
}Espai lògic d’un procés (Relatives): Adreces de la memòria que contenen el codi, les dades (inicialitzades i no inicialitzades) i la pila del procés. Aquest espai es crea en el moment d’execució del programa. Per exemple, una variable pot ser referenciada com a 10 bytes des de l’inici de les dades.
Espai físic d’un procés (Absolutes): Adreces de la memòria on es carrega l’espai lògic del procés. Aquestes adreces són les adreces reals a la memòria física on resideixen el codi, les dades i la pila del procés. Quan el sistema operatiu carrega un programa a la memòria RAM, l’espai lògic d’aquest procés es mapeja a adreces físiques específiques, que són les adreces reals on resideixen les instruccions del codi i les dades.
Adreces generades per la CPU (adreces virtuals): Quan un procés executa codi, la CPU genera adreces virtuals (també anomenades adreces lògiques) per accedir a variables, instruccions o la pila. Aquestes adreces no són adreces físiques, sinó referències dins l’espai d’adreces del procés. Aquestes adreces virtuals no poden accedir directament a la memòria RAM; han de ser traduïdes a adreces físiques mitjançant algun mecanisme de reubicació.

Repte del SO: Com es tradueixen les adreces lògiques a físiques?
Suposem que tenim dos programes carregats en zones de memòria diferents:

El programa A espera que la instrucció MOV estigui a la posició 24 de la memòria, i el programa B espera que la instrucció CMP estigui a la posició 28 de la memòria. Si no tenim un mecanisme de reubicació de la memòria, les seves expectatives es veuran compromeses. Fixeu-vos que cada programa té la seva zona de 16KB però es poden solapar. Necesitem un mecanisme que ens permeti reubicar la memòria.
L’espai d’adreçament d’un programa s’ha de reubicar (traduir) segons on el sistema operatiu decideixi carregar-lo a Memòria, sense modificar-ne el comportament. Aquesta traducció pot fer-se en compilació, càrrega o execució.
Les adreces físiques del programa es generen durant la compilació. El lloc on el procés s’executarà és conegut i fix.
El programa conté adreces lògiques.
La CPU genera sempre adreces virtuals. La traducció a adreces físiques es fa cada vegada que hi ha un accés a memòria, per hardware:


Cada pàgina del procés té associats diversos bits de protecció dins la seva Page Table Entry (PTE):
Quan la CPU accedeix a una adreça virtual:
Aquest procediment el veurem en detall quan parlem de memòria virtual.
La CPU funciona en dos modes:
La protecció per pàgines garanteix que un procés d’usuari no pugui llegir ni modificar memòria del SO.

El glitch es produeix perquè l’adreçament directe a la memòria no està subjecte a cap traducció o verificació en temps d’execució, i el motor del joc tracta adreces fora del rang del nivell com a accessibles, interpretant-les erròniament com a dades vàlides.




La fragmentació es refereix a les àrees de memòria no utilitzades, i pot ser causada pel tipus de mecanisme de gestió de la memòria.
Interna. Porció de Memòria d’una partició que no utilitza el procés té menys requeriments. Suposem que assignem una partició de memòria de 1000 bytes a un procés, però el procés només necessita 800 bytes. Els 200 bytes restants es considerarien fragmentació interna.
Externa. Es produeix quan existeix espai de Memòria lliure per satisfer els requeriments, però no és contigua i per tant no el podem utilitzar. Imagineu que tenim dues àrees de memòria lliure de 300 bytes cada una, però estan separades per una àrea ocupada de 200 bytes, no podem satisfer una sol·licitud de 500 bytes, tot i que hi ha prou memòria lliure en total.
La fragmentació és un problema que afecta l’eficiència de l’ús de la memòria en els sistemes informàtics.

A diferència de les particions de mida fixa, les particions de mida variable permeten que la mida de la partició s’adapti a les necessitats del procés.
Observació
El nombre de processos pot augmentar si es fa compactació periòdica per reduir la fragmentació externa.
Per exemple, si tenim una partició de 100KB i un procés de 50KB, la partició de mida fixa tindrà 50KB de fragmentació interna, mentre que la partició de mida variable tindrà 0KB de fragmentació interna.


La paginació implica que el mapa de Memòria es divideix en pàgines i la Memòria principal es divideix en un marc de pàgines. Un marc de pàgina conté en un moment determinat una pàgina en memòria d’un procés. Aquesta estructura de dades que relaciona pàgines amb marcs es coneix com a taula de pàgines i s’utilitza en la traducció.

Què representa ×n en aquests diagrames?
El símbol ×n indica que cada entrada d’una taula (segmentació, paginació o similar) ocupa n bytes. Per accedir a una entrada concreta, cal calcular la seva adreça amb: \(\text{adreça_física} = \text{base_taula} + (\text{índex} \times n)\)
| cel·la pàgina física | V | R | W | X | M | Ref |
|---|
Disposem d’un sistema de gestió de Memòria paginat amb els paràmetres següents:
Calcular:
L’adreça lògica és dividida en dues parts: el desplaçament i el número de pàgina.
L’adreça lògica és dividida en dues parts: el desplaçament i el número de pàgina.
Quina és l’adreça física de les adreçes lògiques: 015253H, 003204H, 0H, 017253H, 005100H. Quines són vàlides? Assumeix la següent taula de pàgines:
Taula de pàgines
| Index | Cel·la | V |
|---|---|---|
| 0 | 09H | 1 |
| 1 | 01H | 1 |
| 2 | 03H | 0 |
| 3 | 0FH | 1 |
| 4 | 02H | 1 |
| 5 | 0CH | 0 |
| 21 | 0AH | 1 |
| 22 | 05H | 1 |
| 23 | 0DH | 1 |
| 24 | 04H | 0 |
| 25 | 00H | 0 |
Solució
| Adreça lògica | Cel·la | Desplaçament | Adreça física | Vàlida |
|---|---|---|---|---|
| 015253H | ??? | ??? | ??? | ??? |
| 003204H | ??? | ??? | ??? | ??? |
| 0H | ??? | ??? | ??? | ??? |
| 017253H | ??? | ??? | ??? | ??? |
| 005100H | ??? | ??? | ??? | ??? |
Donada una adreça lògica amb 9 bits per al número de pàgina i 12 bits per al desplaçament, com ara l’adreça 015253H, podem descomposar-la de la següent manera:
015253H en binari: 0 0001 0101 0010 0101 00110 0001 0101 que en decimal és el 21 (\(2^0+2^2+2^4\)).015253H en binari: 0 0001 0101 0010 0101 00110010 0101 0011 (253H).Per tant, cercarem la pàgina nº 21 a la taula de pàgines, aquesta entrada conté el número de cel·la 0AH. Per tant, l’adreça física és 0A253H i és vàlida.
Quina és l’adreça física de les adreçes lògiques: 015253H, 003204H, 0H, 017253H, 005100H. Quines són vàlides? Assumeix la següent taula de pàgines:
Taula de pàgines
| Index | Cel·la | V |
|---|---|---|
| 0 | 09H | 1 |
| 1 | 01H | 1 |
| 2 | 03H | 0 |
| 3 | 0FH | 1 |
| 4 | 02H | 1 |
| 5 | 0CH | 0 |
| 21 | 0AH | 1 |
| 22 | 05H | 1 |
| 23 | 0DH | 1 |
| 24 | 04H | 0 |
| 25 | 00H | 0 |
Solució
| Adreça lògica | Cel·la | Desplaçament | Adreça física | Vàlida |
|---|---|---|---|---|
| 015253H | 0AH | 253H | 0A253H | Sí |
| 003204H | 0FH | 204H | 0F204H | Sí |
| 0H | 09H | 0H | 09000H | Sí |
| 017253H | 0DH | 253H | 0D253H | Sí |
| 005100H | 0CH | 100H | 0CH10H | No |
Assumeix que tenim un sistema on la mida de la pàgina és de 4 KB. Si un procés ocupa 10 KB de memòria, aquest s’allotjarà en tres pàgines (4 KB + 4 KB + 2 KB). Això implica que el procés ocuparà 3 cel·les de la Memòria Principal. Si el procés necessita 10 KB de memòria, però la mida de la pàgina és de 8 KB, el procés s’allotjarà en dues pàgines (8 KB + 2 KB). Això implica que el procés ocuparà 2 cel·les de la Memòria Principal. Per tant:
La paginació no evita la fragmentació interna, però la redueix.
La paginació és una tècnica de gestió de memòria que presenta certes característiques:
Eliminació de la Fragmentació Externa: Cada pàgina pot ser assignada independentment, permetent a les pàgines ser ubicades en qualsevol ordre a la memòria física. Això elimina la dependència de tenir àrees contigües per allotjar processos.
Fragmentació Interna: Tot i que elimina la fragmentació externa, la paginació pot introduir fragmentació interna, ja que l’última pàgina pot no estar plena. Aquest espai no utilitzat dins de l’última pàgina indueix a fragmentació interna.
Transparència a l’Usuari: Aquest esquema de gestió de memòria és totalment transparent a l’usuari. L’usuari no necessita saber res sobre la paginació.
Taula de Pàgines per Procés: Es necessita mantenir una taula de pàgines per a cada procés per gestionar la traducció d’adreces lògiques a adreces físiques.
La paginació elimina la fragmentació externa des del punt de vista del procés. Tanmateix, en implementacions modernes pot aparèixer una certa fragmentació al gestor de frames (buddy allocator), tot i que molt menor que en particions variables.
La segmentació és un mètode de maquinari que intenta donar suport a les regions. Considera el mapa de memòria d’un procés com un conjunt de segments. Cada regió es guarda en un segment diferent. El maquinari del gestor necessita una taula de segments. Una direcció lògica es forma per un número de segment i una direcció dins del segment. La traducció consisteix a accedir al número de segment i utilitzar els registre base i límit per comprovar que l’entrada és correcta.

La segmentació és molt semblant amb l’esquema de gestió de Memòria per particions múltiples de mida variable. Té els mateixos problemes que aquest esquema.
Fragmentació Externa. L’espai de memòria física d’un segment ha de ser contigu en memòria i pot provocar fragmentació externa. Imaginem que tenim 3 segments de 1KB, 2KB i 2KB. La nostra taula de segments ens portarà a 3 zones de memòria física de 1KB, 2KB i 2KB. Assumirem que ambdos segments de 2KB no estan utilitzats, per tant, tenim 4KB de memòria lliure. No obstant això, no podem allotjar un segment de 3KB, ja que no hi ha cap regió contigua de 3KB.
Requereix mètodes de compactació de la Memòria. Per gestionar la fragmentació, es poden utilitzar mètodes de compactació que moguin els segments i redueixin la fragmentació. Es poden moure segments després d’un ús continuat o quan es detecta que hi ha fragmentació.
Polítiques de selecció per ubicar els segments en Memòria física: S’han d’escollir algoritmes eficients per ubicar els segments a la memòria física, com ara First-Fit o Best-Fit.
Absència de Fragmentació Interna: Cada segment pot tenir la seva pròpia mida, i això significa que no hi ha fragmentació interna dins dels segments mateixos. Cada segment utilitza exactament l’espai que necessita sense desperdiciar memòria.
Flexibilitat per compartir i protegir segments: Cada segment pot ser protegit individualment i compartir-se amb altres processos si és necessari. Aquesta capacitat de gestionar diferents parts de la memòria amb polítiques específiques proporciona un alt grau de control i eficàcia en la gestió del sistema.
Per exemple, un segment de codi pot ser compartit per diferents processos, mentre que un segment de dades pot ser protegit per un procés específic.
La segmentació paginada proporciona suport directe a les regions d’un procés i la paginació permet un millor aprofitament de la Memòria i una base per construir un esquema de Memòria virtual.

Observació
Aquest model és molt útil per entendre conceptes, però no és el que implementen els sistemes operatius moderns com Linux o Windows.
Dissenyar un sistema de segmentació paginada amb les característiques següents:
Calcular:
Nº de segments: 16 segments per procés. Per tant, necessitem 4 bits per representar el número de segment (\(2^4\)).
Mida màxima segment: 1MB. Per tant, necessitem 20 bits per representar el desplaçament dins del segment (\(2^{20}\)).
Mida de la pàgina: 4KB. Per tant, necessitem 12 bits per representar el desplaçament dins de la pàgina (\(2^{12}\)).
Adreça lògica: Segment (4 bits) + Desplaçament 1 (20 bits).
Adreça lògica: Segment (4 bits) + Pàgina (8 bits) + Desplaçament 2 (12 bits).
Adreça física: Cel·la (11 bits) + Desplaçament 2 (12 bits). La mida de la Memòria Principal és de 8MB, per tant, necessitem 23 bits per representar el número de cel·la (\(2^{23}\)). La raó entre la mida de la Memòria Principal i la mida de la pàgina és: (\(\dfrac{2^{23}}{2^{12}}=2^{11}\)).

La paginació segmentada primer divideix en taula de pàgines i després cada pàgina es divideix en segments.
En l’únic cas que pot ser eficient es quan tenim processos molt grans
Disposem d’un sistema de gestió de memòria on la mida de la pàgina és de 512 bytes, la de Memòria és de 2 MB, i la d’una paraula 1 byte. Un procés consta de com a molt 4 segments. La mida màxima d’un segment és 4K. Totes les taules s’implementen en memòria principal. Donats els dos processos següents:
| P1 | P2 | |
|---|---|---|
| \(P_{A}\) (512 bytes) | X | X |
| \(P_{B}\) (2560 bytes) | X | |
| \(Dades_{L}\) (1024 bytes) | X | X |
Les X’s en la taula indiquen quins procediments i dades estan assignats a cada procés. Una fila amb dos o més X’s indica que el procediment o dades estan compartits. A més, cada procés està format per un segment d’stack de 1 KB. Les primeres 50 primeres cel·les estan ocupades, i de les restants, les parells també ho estan.
Doneu un exemple, sempre que sigui possible, que mostri quina és la informació i la seva mida (en bytes), que ha de guardar el s.o. per tal de poder fer la traducció d’adreces dels dos processos quan aquests executen dins de la CPU pels sistemes de gestió de memòria següents:

Pàgines per procés:
| P1 | P2 | |
|---|---|---|
| \(P_{A}\) (512 bytes) | ? | ? |
| \(P_{B}\) (2560 bytes) | ? | ? |
| \(Dades_{L}\) (1024 bytes) | ? | ? |
| Stack (1024 bytes) | ? | ? |
| TOTAL | ? | ? |
Pàgines per proés:
| P1 | P2 | |
|---|---|---|
| \(P_{A}\) (512 bytes) | 1 | 1 |
| \(P_{B}\) (2560 bytes) | 5 | - |
| \(Dades_{L}\) (1024 bytes) | 2 | 2 |
| Stack (1024 bytes) | 2 | 2 |
| TOTAL | 10 | 5 |


No es pot aplicar la segmentació


En els sistemes operatius moderns (Linux, Windows, macOS), la gestió de la memòria es basa principalment en paginació amb suport de la MMU, TLB i taules de pàgines multinivell. Aquest és el mecanisme central de traducció d’adreces en arquitectures modernes com x86-64 i ARM.
La segmentació clàssica i la segmentació paginada són models teòrics o històrics que permeten entendre els fonaments de la gestió de la memòria, però ja no s’utilitzen com a mecanisme general en arquitectures actuals.
Tot i això, Linux sí que utilitza segmentació en casos puntuals, especialment: - per accedir a informació específica de cada procés o fil (FS/GS base, TLS), - en modes de compatibilitat de 32 bits, - i en fases inicials del procés d’arrencada.
Part 2 — Sistemes moderns: el cas del Kernel de Linux
Traducció d’adreces real, TLB, multilevel paging, ASLR, estructura /proc/<pid>/maps, ELF, mmap(), COW, i assignació física (buddy allocator).
Part 3 — Memòria virtual
Demand paging, page faults, swapping, working set, thrashing, polítiques de reemplaçament i gestió dinàmica de la memòria virtual.

Unitat 6 · Sistemes Operatius (SO) 🏠