Come questo processo gioca fuori è per lo più l'autore del driver e l'hardware , ma per i piloti che ho guardato o scritta e l'hardware con cui ho lavorato, questo è di solito il modo in cui funziona:
- a inizializzazione del conducente, che assegnerà un certo numero di buffer e dare a questi a il NIC.
- Quando un pacchetto viene ricevuto dalla scheda NIC, estrae l'indirizzo successivo dal relativo elenco di buffer, inserisce i dati direttamente in esso e notifica il driver tramite un interrupt.
- Il driver riceve l'interrupt e può trasformare il buffer nel kernel oppure allocare un nuovo buffer del kernel e copiare i dati. "Zero copy networking" è il primo e ovviamente richiede supporto dal sistema operativo. (più in basso su questo)
- Il driver deve allocare un nuovo buffer (nel caso zero-copy) o riutilizzerà il buffer. In entrambi i casi, il buffer viene restituito alla scheda NIC per i pacchetti futuri.
La rete a zero copie all'interno del kernel non è poi così male. Zero-copia fino in fondo a terra utente è molto più difficile. Userland riceve i dati, ma i pacchetti di rete sono costituiti sia dall'intestazione che dai dati. Per lo meno, la vera copia zero verso l'utente richiede il supporto dalla scheda NIC in modo che possa pacchetti DMA in buffer di intestazione/dati separati. Le intestazioni vengono riciclate una volta che il kernel instrada il pacchetto verso la sua destinazione e verifica il checksum (per TCP, nell'hardware se la NIC lo supporta o nel software se non lo fa; nota che se il kernel deve calcolare il checksum stesso, sarebbe può anche copiare i dati: osservare i dati comporta perdite nella cache e copiarli altrove può essere gratuito con il codice sintonizzato).
Anche supponendo che tutte le stelle siano allineate, i dati non sono effettivamente nel buffer utente quando vengono ricevuti dal sistema. Fino a quando un'applicazione richiede i dati, il kernel non sa dove andrà a finire. Si consideri il caso di un demone multi-processo come Apache. Esistono molti processi figlio, tutti in ascolto sullo stesso socket. È inoltre possibile stabilire una connessione, fork()
, ed entrambi i processi sono in grado di immettere recv()
dati in entrata.
I pacchetti TCP su Internet sono in genere 1460 byte di payload (MTU di 1500 = 20 byte intestazione IP + 20 byte intestazione TCP + 1460 byte dati). 1460 non è una potenza di 2 e non corrisponde a una dimensione di pagina su nessun sistema che troverai. Questo presenta problemi per il riassemblaggio del flusso di dati. Ricorda che TCP è orientato al flusso. Non vi è alcuna distinzione tra le scritture del mittente e due scritture da 1000 byte in attesa verranno ricevute interamente in una lettura di 2000 byte.
Considerando ciò, considerare i buffer utente. Questi sono assegnati dall'applicazione. Per poter essere usato per zero-copy fino in fondo, il buffer deve essere allineato alla pagina e non condividere quella pagina di memoria con qualcos'altro. Al tempo recv()
, il kernel potrebbe teoricamente rimappare la vecchia pagina con quella contenente i dati e "capovolgerla" in posizione, ma ciò è complicato dal problema del riassemblaggio visto che i pacchetti successivi si troveranno su pagine separate. Il kernel potrebbe limitare i dati che restituisce al carico utile di ogni pacchetto, ma ciò comporterà molte chiamate di sistema aggiuntive, rimappatura delle pagine e probabilmente una minore velocità complessiva.
Sto solo graffiando la superficie su questo argomento. Ho lavorato in un paio di società nei primi anni del 2000 cercando di estendere i concetti di copia zero in terra d'utenza. Abbiamo persino implementato uno stack TCP in userland e abbiamo eluso il kernel interamente per le applicazioni che utilizzavano lo stack, ma questo ha portato il suo insieme di problemi e non è mai stato di qualità di produzione. È un problema molto difficile da risolvere.
fonte
2010-04-27 17:16:18
Google per la copia in rete zero ... pochissimi dispositivi ad alta velocità possono tollerare la doppia copia sul kernel, quindi l'utente in questi giorni. IANANG (I Am Not A Network Guru) ma credo che DMA sia usato in modo aggressivo –
Quindi oggigiorno, una volta che una NIC cattura un pacchetto, sarà copiato direttamente nella memoria (utente)? – Rayne
@ Rayne sì; la NIC utilizzerà il DMA per trasferire i dati direttamente nella memoria fisica mappata nello spazio degli indirizzi del processo (userland). – vladr