Consiglio: si studia sui libri, scritti da gente che lo fa per mestiere, NON SUI FORUM o sui pseudocorsi ONLINE !!!!!!!
La frase che hai indicato:
il codice della funzione printf starà su una sola pagina di memoria reale che farà da supporto a tutte le pagine di memoria virtuale di tutti i processi che hanno detta funzione nel loro codice
e' incomprensibile pure per chi fa il programmatore di mestiere da 20 anni!
La faccio breve, perche' per rispondere dovrei scrivere l'equivalente di diversi capitoli diun libro!
Non voglio andare nei dettagli della terminologia Linux, ma ora uso itermini cosi' come vengono utilizzati in qualunque testo di teoria dei sistemi operativi:
1) processi e thread sono oggetti concettualmente distinti
1.1) i processi sono gestiti dal sistema operativo, due processi non comunicano tra di loro direttamente, ma solo attraverso dei meccanismi di interprocess comunication, una cosa simile alla comunicazione via rete (se non addirittura esattamente quella)
Ogni processo ha la sua memoria, i suoi thread, e puo' accedere alle risorse del S.O. solo chiedendole a quest'ultimo, il quale controlla che non vengano usate male da piu' rocessi contemporanemanete. Tra l'altro, ogni processo ha il suo codice, il suo stack, ecc.
Per quanto riguarda le librerie dinamiche, vedremmo dopo
1.2) i threa vivono all'interno di un processo. Un thread di esecuzione e' una funzione che viene mandata in esecuzione in parallelo all'esecuzione del programma in cui il thread e' stato creato.
Ogni thread ha un proprio stack, ma condivide la memoria e le variabili globali con tutti i thread del processo. Ovviamente ogni processo deve avere almeno un thread.
Inoltre i thread eseguno il codice associato al processo. Quindi thread distinti possono eseguire lo stesso identico codice (ricorda che ogni thread ha un suo stack)
Librerie statiche
-----------------------
Una libreria statica e' un insieme di funzioni salvate su file e che vengono caricate dal processo quando questo parte.
Se due processi usano la stessa libreria, ogn'uno carica la sua copia.
Librerie dinamiche
--------------------------
Una libreria dinamica e' come una libreria statica, solo che il sistema operativo si assicura che il codice venga caricato in memoria una sola volta.
Ma ovviamente, anche se il codice e' stato caricato una sola volta, le variabili globali definite all'interno della librerai devono NECCESSARIAMENTE essere associate ad ogni processo, se no sai che disastro!
Quindi
---------
Come fa una funzione a sapere a che processo appartiene?
Semplice: perche' viene eseguita da un thread che appartiene a quel processo.
Inoltre, se utilizza delle variabili statiche inizializzate, queste sono state inizializzate specificatamente da quel processo (come dicevo, ogni processo ha la sua copia delle variabili globali).
Applicazione->Libreria->Sistema Operativo
--------------------------------------------------------------
Come fa tutto l'ambaradan a funzionare senza casini?
Concettualmente il sistema e' semplice: partizionamento.
1) il sistema operativo mette a disposizione le primitive per accedere alle risorse globali (memoria, filesystem, tastiera, monitor, ...) e si assicura di coordinare le richieste da parte dei vari processi
2) la libreria usa le primitive per accedere alle risorse globali, e si assicura di coordinare le rihieste da parte di piu' thread. Se non lo facesse, sai che disastro
3) l'applicazione usa la libreria. E se l'applicazione e' multithreading, chi scrive il codice deve assicurarsi che la funzione di libreria che andra ad utilizzare sia thread-safe. Se non lo e', deve implementare i meccanismi di controllo della concorrenza necessari.
Non tutto e' threads safe
------------------------------------
Assicurare il controllo della concorrenza e' un'operazione estremamente pesante e che serve molto raramente. Per cui, in generale, si preferisce un'implementazione efficiente da un'implementazione thread-safe.
E' ovvio che certe funzionalita' DEVONO NECCESSARIAMENTE essere thread-safe.
I casi piu' banali sono, ovviamente:
1) la creazione di threa
2) l'allocazione della memora
3) la scrittura su standard output
Concludendo
-------------------
STUDIA SUI LIBRI
E', ovviamente, questa e' una spiegazione spannometrica.
Per capirne di piu', bisogna studiare sui libri