2010-05-05 7 views
8

In Linux, quando si effettua un I/O di blocco chiamato come letto o accettato, cosa succede realmente?In che modo funziona effettivamente Linux che blocca l'I/O?

I miei pensieri: il processo viene estratto dalla coda di esecuzione, messo in attesa o bloccato su una coda di attesa. Quindi quando viene effettuata una connessione TCP (per accettare) o il disco rigido è pronto o qualcosa per un file letto, viene generato un interrupt hardware che consente a quei processi in attesa di svegliarsi ed eseguire (nel caso di un file letto, come Linux sa quali processi si devono risvegliare, poiché potrebbero esserci molti processi in attesa su file diversi?). O forse invece degli interrupt hardware, il singolo processo esegue il polling per verificare la disponibilità. Non sono sicuro, aiuto?

+0

È praticamente ha colpito il chiodo sulla testa (tranne che per l'ultima osservazione, non ci sono sondaggi, per la maggior parte). Il multiplexing tra più server e file viene eseguito dal kernel, che è un processo invisibile che coordina cose come questa per conto di tutti gli altri processi. –

risposta

0

Leggi questo: http://www.minix3.org/doc/

E 'molto, chiaro, molto facile da capire spiegazione. In genere si applica anche a Linux.

0

effectivly Il metodo restituisce solo quando il file è pronto per leggere, quando i dati sono su un socket, quando una connessione è arrivato ...

Per assicurarsi che può tornare immediatamente probabilmente si desidera utilizzare il Chiamata di sistema Select per trovare un descrittore di file pronto.

11

Ogni dispositivo Linux sembra essere attuate in modo leggermente diverso, e il modo preferito sembra variare ogni tot Linux rilascia quando si aggiungono/caratteristiche più sicuri più veloci del kernel, ma in generale:

conducente
  1. Il dispositivo crea leggere e scrivere code di attesa per un dispositivo.
  2. Qualsiasi thread di processo che desidera attendere per I/O viene inserito nella coda di attesa appropriata. Quando si verifica un'interruzione, , il gestore riattiva uno o più thread in attesa di . (Ovviamente i thread non vengono eseguiti immediatamente come nel contesto dell'interrupt , ma vengono aggiunti alla coda di pianificazione del kernel ).
  3. Quando è pianificato dal kernel, il thread verifica se le condizioni sono corrette per continuare, se non lo è torna nella coda di attesa.

Un tipico esempio (leggermente semplificata):

Nel driver a inizializzazione:

init_waitqueue_head(&readers_wait_q); 

In funzione di lettura di un conducente:

if (filp->f_flags & O_NONBLOCK) 
    { 
     return -EAGAIN; 
    } 
    if (wait_event_interruptible(&readers_wait_q, read_avail != 0)) 
    { 
     /* signal interrupted the wait, return */ 
     return -ERESTARTSYS; 
    } 
    to_copy = min(user_max_read, read_avail); 
    copy_to_user(user_buf, read_ptr, to_copy); 

Quindi il gestore di interrupt solo numeri:

wake_up_interruptible(&readers_wait_q); 

Si noti che wait_event_interruptible() è una macro che nasconde un ciclo che verifica una condizione - read_avail != 0 in questo caso - e si aggiunge ripetutamente alla coda di attesa se risvegliata quando la condizione non è vera.

Come già detto, vi sono diverse varianti: la principale è che se c'è potenzialmente molto lavoro da fare per il gestore di interrupt, si limita a fare il minimo indispensabile e rimanda il resto a una coda di lavoro o a un tasklet (generalmente noto come "metà inferiore") ed è questo che sveglia i fili in attesa.

See Linux Device Driver libro per maggiori dettagli - pdf disponibile qui: http://lwn.net/Kernel/LDD3