2011-02-23 17 views
11

Scenario ipotetico: Un flusso di pacchetti udp arriva alla macchina X, che sta eseguendo due programmi - uno che sta ascoltando i pacchetti con recv(), e un altro che sta eseguendo pcap.Come funziona il buffering di pcap unix?

In questo caso, a quanto ho capito, i pacchetti vengono memorizzati nell'interfaccia finché non viene interrogato dal kernal, che quindi li sposta in un buffer nella memoria di kernals e copia i pacchetti in altri due buffer: uno buffer per il programma in ascolto con recv e un buffer per il programma in ascolto con pcap. I pacchetti vengono rimossi dal rispettivo buffer quando vengono letti, sia da pcap_next() che da recv(), la volta successiva che viene eseguito dallo scheduler dei processi (presumo che stiano bloccando in questo caso). È corretto? Ci sono veramente 4 buffer usati o è gestito in altro modo?

Sto cercando una descrizione, il più dettagliata possibile, su quali buffer sono realmente coinvolti in questo caso e su come i pacchetti si spostano da uno all'altro (ad esempio un pacchetto viene copiato nel buffer di pcaps prima che vada al recv buffer, dopo o undefined?).

So che questa sembra una grande domanda, ma tutto quello che mi interessa davvero è dove viene memorizzato il pacchetto, e per quanto tempo rimane lì per. I punti elenco vanno bene. Idealmente mi piacerebbe una risposta generale, ma se varia tra il sistema operativo sono più interessato a Linux.

risposta

8

caso Linux (BSD sono probabilmente in qualche modo simile, usando mbuf s anziché skbuff s):

Linux utilizza skbuffs (buffer socket) di buffer dati di rete. Uno skbuff contiene metadati su alcuni dati di rete e alcuni indicatori di tali dati.

I rubinetti (utenti pcap) creano cloni di skbuff. Un clone è un nuovo skbuff, ma punta agli stessi dati. Quando qualcuno ha bisogno di modificare i dati condivisi da diversi skbuff (lo skbuff originale e i suoi cloni), deve prima creare una nuova copia (copy-on-write).

Quando qualcuno non ha più bisogno di uno skunk, lo è kfree_skb(). kfree_skb() decrementa un conteggio dei riferimenti e quando il conteggio dei riferimenti raggiunge lo zero, lo skbuff viene liberato. È leggermente più complicato spiegare i cloni, ma questa è l'idea generale.

+0

Quindi, stai dicendo che la funzione recv() usa il buffer dei kernel, ma ogni istanza di pcap ha la propria copia del buffer? In quale fase vengono realizzati questi cloni - quando il pacchetto viene ricevuto? quando papcap vuole leggerlo? – Benubird

+0

Ogni istanza di pcap ha una propria copia dei metadati, ma condividono tutti gli stessi dati. I cloni sono fatti quando il pacchetto viene ricevuto (in 'skb_deliver()' IIRC). – ninjalj