2009-12-12 2 views
7

Sto eseguendo 2 thread (presumo che siano pthreads per il momento). Thread_1() effettua una chiamata API definita dall'utente che alla fine funziona nel kernel. Thread_2() è totalmente nello spazio utente.È possibile anticipare un thread nel mezzo di una chiamata di sistema al kernel?

La mia domanda è: Can Thread_2() inizia l'esecuzione pre-empting Thread_1() mentre la chiamata API è in corso, il controllo è da qualche parte all'interno del kernel? In caso contrario, perché, e se voglio che questo scenario si verifichi (per qualsiasi motivo), cosa devo fare?

risposta

5

Se si sta chiedendo se una chiamata kernel di blocco come uno fread() che richiede l'IO disco può essere prevenuta, quindi sì.

In particolare, una chiamata di blocco in pratica inserisce Thread_1 in stato di attesa durante l'attesa per qualsiasi cosa stia aspettando. Se Thread_1 è addormentato, sarà programmato l'avvio di Thread_2 (a meno che non ci sia qualcosa di più importante in attesa di essere eseguito).

Edit: Se si desidera un modo di essere "abbastanza fiducioso" che Thread_1 sta eseguendo una chiamata di blocco, fanno Thread_2 priorità inferiore rispetto Thread_1 (in modo che in genere non si corsa a meno che Thread_1 è bloccato) e quando viene eseguito, eleva la sua priorità a un livello superiore rispetto a Thread_1 fino a quando non è stato consegnato l'interrupt hardware, a quel punto abbassa la sua priorità e chiama sched_yield().

+0

In realtà questo presuppone che il tuo i thread sono gestiti dal kernel. E alcuni kernel possono variare. – Artelius

+0

Puoi chiarire la differenza tra la gestione del kernel e quella non gestita dal kernel? Quali variazioni esistono? – TCSGrad

+0

I thread non gestiti dal kernel sono visti dal kernel come un singolo processo. Il processo internamente (senza supporto del kernel) pianifica i vari thread. Di solito se uno di questi thread si blocca, l'intero processo viene visto come bloccato dal kernel e quindi non viene eseguito alcun thread. Se i thread sono gestiti dal kernel, la maggior parte dei kernel eseguirà altri thread se un thread si blocca. È possibile eseguire un semplice test in cui un thread richiama ripetutamente un syscall e un altro produce ripetutamente. Se il thread di rendimento ottiene un runtime, significa che syscall è un punto di prelazione. – Artelius

8

chiede al kernel sono considerati sia bloccare o non bloccante. Una chiamata bloccante (come ad esempio l'attesa di dati da leggere da un socket di rete) può certamente essere prevenuta senza alcuna azione da parte dell'utente. Gli altri thread continueranno a essere eseguiti. Le chiamate al kernel non bloccanti possono essere considerate molto veloci e, in termini pratici, non importa se puoi effettivamente prevederle o meno.

Generalmente, quando si scrive codice multithread, ci si concentra su come questi thread interagiscono tra loro e si lascia la loro interazione con il kernel fino al kernel da gestire. È progettato per fare un buon lavoro.

+0

Bene, in questo caso, sto scrivendo un test per l'API e i piani di test prevedono l'analisi di ciò che accade quando c'è un interrupt HW (può essere avviato da Thread_2() mentre si trova nello spazio utente) nel mezzo l'esecuzione dell'API. Quindi, idealmente mi piacerebbe Thread_1 (_ per poter cedere nel mezzo dell'esecuzione dell'API, dare il controllo a Thread_2() (iniziando una sequenza che porterebbe ad un interrupt HW), tornando a Thread_1() e riprendere l'esecuzione - se l'API può mantenere il suo stato/salvataggio ecc. mentre l'interrupt HW effettivamente lo colpisce, allora va tutto bene! – TCSGrad

+0

Potresti voler vedere l'approccio alternativo che stavo pensando in questo http://stackoverflow.com/ domande/1885903/how-to-call-ac-function-from-random-places-inside-another-function. Puoi anche saltarlo - tutte le informazioni sono proprio qui in questa domanda! :) – TCSGrad

7

Dipende dal kernel. I kernel classici non consentivano la prelazione (tranne che in punti specifici quando dormiva in un thread). Ma i kernel più recenti hanno iniziato a consentire il preemption all'interno del kernel stesso.

Linux supporta un kernel interrompibile quando è stato creato con CONFIG_PREEMPT. Dalla documentazione del kernel:

Questa opzione riduce la latenza del kernel rendendo tutto il codice del kernel (che non è l'esecuzione in una sezione critica) preemptible. Ciò consente di reagire agli eventi interattivi di consentendo di anticipare involontariamente un processo a bassa priorità anche se è in modalità kernel eseguendo una chiamata di sistema e altrimenti non sta per raggiungere un punto di prelazione naturale. Ciò consente alle applicazioni di funzionare più "agevolmente" anche quando il sistema è sotto carico, al costo di un throughput leggermente inferiore e un leggero sovraccarico di runtime al codice del kernel.

Selezionare questa opzione se si sta creando un kernel per un desktop o un sistema integrato con requisiti di latenza nell'intervallo dei millisecondi .