Differenza tra loop di eventi e chiamate / interrupt di sistema

3

Quando crei programmi (come un server socket) progettati per essere eseguiti su un sistema operativo, come Ubuntu, i framework come Qt per C ++ usano qualcosa chiamato ciclo dell'evento principale:

app = new QCoreApplication(argc, argv);
int rc = app->exec()

Ora un linguaggio di programmazione come C o C ++ abilita un programma a effettuare chiamate di sistema attraverso funzioni integrate, come fork () o pthread_create () e usa interrupt software per cambiare la modalità kernel. Ad esempio, il programma può richiedere l'uso del kernel tramite una chiamata di sistema per eseguire istruzioni privilegiate, come la creazione di processi o le operazioni di input / output. Altri esempi sono aperti, letti, scritti, chiudi, attendi, esegui, apri, esci e uccidi. Tutto ciò può essere realizzato in C / C ++ direttamente senza un ciclo di eventi.

Quindi qual è lo scopo del ciclo degli eventi?

    
posta JohnMerlino 05.01.2014 - 22:23
fonte

3 risposte

3

Il confronto tra il ciclo di eventi e le chiamate di sistema è simile al confronto tra mele e .... automobili e non solo auto arancioni.

Le chiamate di sistema vengono utilizzate come parte del normale flusso di controllo strutturato. Fai X, Y, chiamata di sistema poi Z. Come hai sottolineato, lo scopo delle chiamate di sistema è di fornire l'app ai sottosistemi gestiti dal kernel. Dal momento che tali sottosistemi sono condivisi / accessibili da più processi, è necessario attraversare il confine dall'utente nello spazio del kernel per poter lavorare con essi.

I loop degli eventi, d'altra parte, vivono completamente nel tuo spazio utente. Sono la base di un Event Driven Programming (EDP) , che è un'applicazione GUI molto comune ma ha anche usi in molte altre aree. Invece di avere una struttura di controllo che fa "X, Y, sleep, Z, system call ..." in EDP si definiscono piccoli frammenti di codice (cioè gestori di eventi) e il loro compito è di rispondere a particolari eventi. Il ciclo degli eventi è ciò che invia quegli eventi ai rispettivi gestori, al livello più elementare, non è altro che una coda e una tabella di ricerca con i puntatori di funzione.

Poiché le applicazioni GUI sono gestite dagli eventi della natura (ad esempio, l'utente fa clic qui e là), i loop degli eventi sono quasi universalmente utilizzati per guidarli. Una ragione per usare gli eventi in una GUI è dire che vuoi che qualcosa lampeggi ogni 2 secondi. Se avessi un'app non GUI, potresti implementare un semplice loop con sleep (2), ma se chiami sleep () in una GUI, l'applicazione si bloccherebbe poiché il loop non risponderebbe più ai clic del mouse / della tastiera dal utente. Il modo per aggirarlo, sarebbe quello di creare un timer che spara un evento ogni 2 secondi. In questo modo il ciclo continuerà a inviare tutti gli altri eventi e ogni 2 minuti verrà richiamato il gestore del timer per cambiare il colore di qualunque cosa tu stia lampeggiando.

Per chiarire cosa è un loop di eventi (in pseudo codice):
   while(true) {
      event = GetEvent()  // will sleep until next event arrives
      DispatchEvent(event)
   }

Questo può essere eseguito praticamente su qualsiasi thread, ma in genere dovrebbe essere su quello principale che ha avviato l'app. All'interno di DispatchEvent, hai semplicemente una mappa di ricerca, che associa i tipi di evento (ad esempio un int) a uno o più gestori di eventi (puntatore di funzione, puntatori di interfacce ... ecc.) Registrati per ascoltare quell'evento.

    
risposta data 05.01.2014 - 23:09
fonte
5

A livello di sistema è tutto uguale. Muovere un mouse, premere un tasto, accarezzare lo schermo, ricevere un pacchetto wireless, questo innesca un interrupt di livello di sistema, che esegue il blocco di codice assegnato all'interrupt.

Tuttavia a un livello più alto ci sono due stili di programmazione distinti comunemente usati.

Il "callback" - > si assegna un blocco del codice da eseguire quando si verifica un evento. Poiché diversi eventi potrebbero sovrapporsi, è necessario che il programma sia multithreading e che i gestori di eventi siano protetti da thread. Il vantaggio è un programma più reattivo, lo svantaggio è lo sforzo extra per garantire la sicurezza del thread e l'impossibilità di testare tutte le possibili combinazioni di eventi.

Il "ciclo degli eventi" - > il pezzo di codice assegnato a un evento registra semplicemente l'evento in una tabella / stack / elenco. Il thread principale del programma esegue quindi la scansione dell'elenco per gli eventi ed esegue il codice necessario per elaborare l'evento. Lo svantaggio è un programma meno reattivo in quanto è necessario completare completamente l'elaborazione di un evento prima di passare a quello successivo, i vantaggi sono il codice più semplice in quanto tutti gli eventi vengono elaborati da un singolo thread e la possibilità di una copertura completa del test.

    
risposta data 06.01.2014 - 02:54
fonte
0

Hai iniziato citando Qt, è un buon punto di partenza. Qt è una libreria GUI. Una GUI di solito funziona con tipi di eventi esterni che potrebbero essere previsti, perché originano nell'attività dell'utente. Ambienti grafici come Windows (Microsoft), X Window, Mac, tutti gli attuali ambienti smartphone / tablet, ecc. Permettono all'utente di fare praticamente qualsiasi input che potrebbe "inviare", come premendo tasti (non solo sulla tastiera), eventi del mouse, gesti dello schermo tattile , ecc.

Se un programma viene scritto in modo sequenziale, l'elaborazione di tutti questi eventi diventa, a livello colloquiale, un livello insopportabile sia di mal di testa che di fastidio allo stesso tempo. Invece di organizzare un programma come evento guidato risolve questo. Esistono generatori di eventi, dispatcher e processori di eventi. Se viene premuto un tasto del mouse, l'evento corrispondente viene inviato a un widget attualmente puntato. In questo caso non è necessario alcun codice complesso per fornire la corrispondenza con il widget e il set di finestre visibili correnti; OTOH, se questo codice fosse stato scritto, sarebbe praticamente identico al codice di distribuzione nel motore basato su loop di eventi.

Allo stesso modo, se scrivo un'applicazione che supporta client 100k su connessioni di rete, non eseguirò l'iterazione per verificare se sono arrivati nuovi dati. Aggiungerò i loro ascolti al motore degli eventi e semplicemente attenderò gli eventi in arrivo nei callback. Non è qualcosa di artificiale - è la conseguenza della naturale evoluzione di trattare con più fonti di eventi, a condizione che "evento" qui sia una definizione astratta di qualcosa a cui il programma deve reagire.

Quindi, i loop di eventi e, in generale, la programmazione basata sugli eventi non è una cosa che contraddice tutte le tecniche che hai menzionato; no, è solo un livello superiore a quello che sono. I gestori di eventi possono quindi utilizzare I / O di file, I / O socket, ecc.

    
risposta data 05.01.2014 - 23:11
fonte

Leggi altre domande sui tag