[so] clarificari mmap

Cosmin Arad so@atlantis.cs.pub.ro
Tue, 16 Dec 2003 19:00:30 -0800 (PST)


Salut,

Fata de grupa 341CA am ramas dator cu 2 explicatii de
la laboratorul de mmap.
Pentru ca nu ne mai intalnim saptamana asta sa le
discutam si pentru ca poate 
mai au si altii aceleasi nelamuriri am trimis aici
lamuririle pentru toata lumea:

1. Am vazut ca daca mapam o pagina WriteOnly (WO) si
incercam sa citim din ea
primim un SIGSEGV. Am mai vazut ca daca incercam sa
scriem ceva si apoi sa citim
nu primim SIGSEGV. Asadar, desi pagina e WO se poate
citi din ea.
Problema este ca arhitectura x86 nu ofera decat 2 biti
de protectie pentru o pagina.
Unul pentru read-only/read-write si unul pentru
user-mode/kernel-mode.
Vezi
http://www.intel.com/design/pentium4/manuals/24547212.pdf,
pagina 137.
Stim ca intrarile din tabela de pagini, cele mai des
folosite sunt tinute in TLB.
Cand procesorul are de translatat o adresa virtuala
intr-o adresa fizica va cauta
pagina din care face parte adresa virtuala in TLB.
Daca o gaseste, face translatarea
dar daca nu genereaza o exceptie (page fault) care
este tratata de sistemul de operare
prin intermediul unui page fault handler. Procesorul
genereaza un page fault in 
mai multe situatii, nu doar aceasta, insa in acest caz
handlerul se va ocupa de
gasirea paginii respective in tabela de pagini,
verificarea protectiei, si daca totul
e ok, "introducerea" ei in TLB.
Vezi
http://lxr.linux.no/source/Documentation/cachetlb.txt.
Asadar in page fault handler se pot verifica bitii de
protectie read, write, execute
si se poate actiona in consecinta, de exemplu prin
trimiterea unui SIGSEGV procesului
care a facut accesul in cazul in care pagina era
protejata impotriva accesului respectiv.
La primul acces, pagina nefiind in TLB se va apela
handlerul care va verifica 
corect bitii de protectie. La al doilea acces pagina
este deja in TLB si la
translatare procesorul va verifica bitii de protectie
disponibili in TLB.
Cum pe x86 avem read-only sau read-write, un read este
permis oricum, de unde
rezulta comportamentul pe care l-am observat la
laborator.
Daca dupa accesul de scriere invalidam TLB-ul, cand
facem citirea pagina nu este in TLB
se va apela din nou page fault handlerul si bitii de
protectie vor fi verificati,
se va observa ca pagina e WO si procesul va primi un
SIGSEGV.

Pentru exemplificare iata un exemplu de test:

#include <stdio.h>
#include <sys/mman.h>

int main(void)
{
	char *ptr, c;
	unsigned int tmpreg;
	
	ptr = mmap(0, 100, PROT_WRITE, MAP_SHARED
		| MAP_ANONYMOUS, 0, 0);
	
	*ptr = 'a'; // scriere

	/* tlb flush */
	__asm__ __volatile__ (
		"movl %%cr3, %0;	\n"
		"movl %0, %%cr3;	\n"
		: "=r" (tmpreg)
		:: "memory");
	
	c = *ptr; // citire
	
	printf("Caracter: '%c'=%d.\n", c, c);
	munmap(ptr, 100);

	return 0;
}

Daca comentam intructiunea de flush, nu se primeste
SIGSEGV. Daca o lasam asa
se primeste la citire.

2. De ce daca faceam o mapare privata a unui fisier in
memorie si faceam modificari acestea nu
erau scrise in fisier. Este normal sa fie asa pentru
ca am interpretat gresit flagul MAP_PRIVATE.
O mapare MAP_PRIVATE presupune ca maparea este privata
procesului respectiv si modificarile
pe care le face el nu sunt vizibile in alta parte,
deci nici in fisier. O mapare MAP_SHARED
nu presupune neaparat ca aceeasi zona e partajata cu
alte procese, ci faptul ca modificarile
facute de un proces sunt vizibile in alta parte deci
si in fisier.
Din acest motiv "nu mergea cu MAP_PRIVATE" :)

Sarbatori fericite!
Cosmin

PS La challenge nu au raspuns decat 4 oameni: Boita
Ioana (341), Murgan Mihai (342),
Hagiescu Andrei si Soptica Irina (346). Va incurajez
sa va uitati inca pe 
semaforul ala. Provocarea e inca deschisa.


__________________________________
Do you Yahoo!?
Protect your identity with Yahoo! Mail AddressGuard
http://antispam.yahoo.com/whatsnewfree