Server in esecuzione nel kernel Linux. L'ascolto dovrebbe avvenire in un thread o no?

StackOverflow https://stackoverflow.com/questions/615483

  •  03-07-2019
  •  | 
  •  

Domanda

Sto scrivendo un client / server nel kernel Linux (Sì. All'interno del kernel. La sua decisione di progettazione è stata presa e finalizzata. Non cambierà)

Il server legge i pacchetti in arrivo da un socket non elaborato. Il protocollo di trasporto per questi pacchetti (su cui è in ascolto il socket raw) è personalizzato e simile a UDP. In breve, non devo ascoltare le connessioni in entrata e quindi fork un thread per gestire quella connessione.

Devo solo elaborare qualsiasi datagramma IP proveniente da quel socket raw. Continuerò a leggere per i pacchetti in un ciclo infinito sul socket raw. Nel programma equivalente a livello di utente, avrei creato un thread separato e continuato ad ascoltare i pacchetti in arrivo.

Ora per il server a livello di kernel, ho dei dubbi sul fatto che dovrei eseguirlo in un thread separato o meno perché:

  1. Penso che read () sia un'operazione di I / O. Quindi da qualche parte all'interno di read (), il kernel deve chiamare la funzione schedule () per rinunciare al controllo del processore. Quindi dopo aver chiamato read () su raw socket, l'attuale contesto attivo del kernel verrà messo in attesa (messo in una coda di sospensione forse?) Fino a quando i pacchetti non saranno disponibili. Quando e quando arriveranno i pacchetti, il contesto di interruzione del kernel segnalerà che il contesto di lettura, che sta dormendo nella coda, è di nuovo pronto per essere eseguito. Sto usando 'contesto' qui apposta invece di 'filo'. Quindi non dovrei richiedere un thread del kernel separato.

  2. D'altra parte, se read () non cede il controllo, l'intero kernel verrà bloccato.

Qualcuno può fornire suggerimenti su come devo progettare il mio server? Qual è l'errore dell'argomento presentato al punto 1?

È stato utile?

Soluzione

Non sono sicuro che tu abbia bisogno di un socket raw nel kernel. All'interno del kernel è possibile aggiungere un hook netfilter o registrare qualcos'altro (???) che riceverà tutti i pacchetti; questo potrebbe essere quello che vuoi.

Se hai DID usato un socket raw all'interno del kernel, allora probabilmente avresti bisogno di un thread del kernel (cioè avviato da kernel_thread) per chiamare read () su di esso. Ma non è necessario che sia un thread del kernel, potrebbe essere un thread dello spazio utente che ha appena effettuato una chiamata speciale di syscall o dispositivo per chiamare la routine in modalità kernel desiderata.

Se hai un hook registrato, il contesto in cui è chiamato è probabilmente qualcosa che non dovrebbe fare troppa elaborazione; Non so esattamente quale possa essere, potrebbe trattarsi di un "gestore di metà inferiore" o "tasklet", qualunque esso sia (questi tipi di strutture di controllo continuano a cambiare da una versione all'altra). Spero che in realtà non sia una routine di servizio di interruzione.


In risposta alla tua domanda originale:

  1. Sì, sys_read bloccherà il thread chiamante, sia esso un thread del kernel o uno spazio utente. Il sistema non si bloccherà. Tuttavia, se il thread chiamante non si trova in uno stato in cui il blocco ha senso, il kernel andrà in panico (programmazione in interrupt o qualcosa del genere)

Sì, dovrai farlo in un thread separato, no non bloccherà il sistema. Tuttavia, effettuare chiamate di sistema in modalità kernel è molto incerto, anche se funziona (in un certo senso).

Ma se invece avessi installato una specie di hook, non avresti bisogno di farlo.

Altri suggerimenti

Penso che la tua scommessa migliore potrebbe essere quella di emulare il modo in cui i driver sono scritti, pensa al tuo server come a un dispositivo virtuale posizionato sopra quelli da cui provengono le richieste. Esempio: un driver del mouse accetta input continui, ma non blocca il sistema se programmato correttamente e una scheda di rete è probabilmente più simile al tuo caso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top