|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
Keyboard Interrupt
Salve ragazzi,
dovrei fare una modifica al kernel in modo che mi memorizzi in una variabile globale (creata da me) quanto tempo ci mette il Kernel a gestire una interruzione di tipo KeyBoard. Credo che dovrò usare il sistema di Timing rdtsc presente sui Pentium: è una funzione assembler e dovrebbe restituirire il valore di certi registri. Gli IRQ da tastiera sono i numeri 1, quindi pensavo di vedere il tempo che trascorre da quando l'IRQ1 si presenta in uno dei registri succitati a quando si ri-presenta dopo essere stato interrotto dagli altri IRQ prioritari. Ma non ho che ho le idee chiarissime..cosa mi consigliate? Lo so che la questione non è stupida, quindi mi rivolgo agli intenditori del Kernel. Grazie 1000 ai cervelloni che sapranno rispondere. |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Re: Keyboard Interrupt
Se vuoi misurare il tempo di latenza dell'irq handler, guarda in drivers/char/pc_keyb.c:keyboard_interrupt.
Nota che la gestione degli irq è fatta in due parti; durante l'irq handler (keyboard_interrupt) le irq sono disabilitate; la gestione vera e propria viene fatta da un tasklet (v. drivers/char/keyboard.c, keyboard_tasklet e relativa funzione kbd_bh) che è eseguita al di fuori di keyboard_interrupt, e con gli irq abilitati (come normale). Tra l'avvento dell'irq e l'avvio del tasklet può ovviamente intercorrere diverso tempo, è questo che devi misurare?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
mmm no, ho letto male, il tasklet si occupa solo di gestire i led, la gestione è un pò più complicata e divisa in più parti. Le funzioni salienti sono
handle_scancode in keyboard.c (eseguita in irq context) console_callback in console.c per la notifica/gestione dei vt (eseguita in process context, con la chiamata schedule_console_callback) Probabilmente sei interessato solo alla parte eseguita in irq context, quindi puoi mettere la misura direttamente in keyboard_interrupt. Nota che durante la gestione gli irq si mantengono disabilitati (non ho verificato in dettaglio ma mi sembra così).
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
Ehi! grazie per la risposta..il discorso è abbastanza tecnico e sono felice che qualcuno risponda.
Quello che io devo misurare è il tempo che intercorre da quando premo il pulsante a quando compare il carattere sullo schermo, ovvero tutto il flusso Input/Output: -Premo tasto -Interruzione al Kernel -Gestione Interruzione da parte di Linux e della CPU. -Ritorno a video di quello che mi aspetto (il carattere premuto appunto) Stop. Il tasklet per i leds che segnali, non dovrebbe interessarmi. Invece l' elenco di operazioni che mi hai elencato nell' ultimo post è interessante. Io immagino che l' IRW da tastiera sia gestito + o - come gli altri, ma con priorità molto bassa: a questo punto devo misurare il tempo di Control Path, incluse le funzioni differite (se mai ce ne sono). Non penso sia difficile..se vuoi parlare + in dettaglio (se ti và di aiutarmi Grazie cmq.. |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
E' un pò complicato quello che vuoi fare. Forse sarebbe meglio misurare il tempo intercorso da quando il tasto viene premuto a quando ad es. un programma utente lo "riceve". Se vai a "cercare" dove e quando viene stampato il carattere sullo schermo, non ne esci più (soprattutto se usi xfree, che non usa il kernel per l'output video).
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
OK, mi va bene anche come dici tu..tecnicamente quello che mi interessa è il tempo di gestione deel' interrupt..ovvero il tempo di Control Path..non so se mi segui..ciao
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Il tempo di gestione dell'irq è semplice da misurare, basta misurare il tempo trascorso dentro pc_keyb.c:keyboard_interrupt().
Nota però che lo smistamento degli eventi della tastiera, una volta gestiti dall'interrupt, è posticipata a un altro kernel task. Quello che farei è: - Prendere nota del tempo all'_entrata_ di keyboard_interrupt. Questo valore può essere esportato in un file dentro /proc. - Un apposito programma utente è in read() su /dev/psaux. Appena arriva un tasto, prende nota dell'istante di arrivo, legge il valore scritto in /proc e tramite differenza misura il tempo trascorso. Questo procedimento funziona sicuramente con XFree _non_ in esecuzione e tastiere ps/2. Se XFree è in esecuzione, potrebbe catturare lui gli eventi della tastiera, col risultato che ti perdi diversi tasti.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
OK, ottima soluzione..ricapitoliamo:
-Piazzo una rdtsc (funziona per gli AMD che tu sappia?) in pc_keyb.c:keyboard_interrupt() . Appena arriva un IRQ da tastiera, mi faccio memorizzare dalla rdtsc il tempo dentro ad una variabile di profiling (che preferisco creare io). - Tu dici: "è in read() su /dev/psaux" . Questa cosa non l'ho mai sentita! Ad intuito, immagino sia il device tastiera e il kernel è in read() ,ovvero in ascolto,degli input su questo device. Intendi questo? -Ti confermo che non è necessario il funzionamento sotto XFREE..mi basta la shell e tastiera PS2. Alla prossima. |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Ok questo programmino è la soluzione; funziona anche sotto XFree:
Codice:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <termios.h>
int main() {
unsigned char k;
int fd = fileno(stdin);
struct termios tty;
tcgetattr(fd, &tty);
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &tty);
while(1) {
read(fd, &k, 1);
/* Mettere la misura qui */
fprintf(stderr, "recv %02x\n", k);
}
return 0;
}
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
Grande!
Che codice ostico...forse perchè non conosco tutte le librerie. (Termios Quindi questo programmino che farebbe? Si mette in ascolto per eventi da tastiera? come dovrei utilizzarlo? Scusa per lo stress, ma mai mi sarei sognato di beccare sul forum uno che si "infilava" nell' argomento ciao |
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Se skifezze di termios servono semplicemente a disabilitare l'echo, a settare il tempo minimo di delay e a impostare la ricezione dei caratteri appena arrivano (di default stdin è line-buffered).
Il funzionamento è semplice: il programma rimane bloccato sulla read finché non è disponibile un carattere in ingresso. Nota che: - Per ogni tasto premuto, vengono generate _più_ interruzioni. Ad es. sul mio sistema la pressione di un tasto normalmente comporta 3 interruzioni. - I dati ricevuti dalla tastiera vengono smistati dal kernel nel layer console, che li gestisce al di fuori del contesto di interruzione. - Il layer console provvede a "tradurre" i tasti in base al layout di tastiera impostato. Nota che alcuni tasti funzione generano _più_ di un "carattere". - Appena un carattere è disponibile nel buffer di lettura, la read() viene "svegliata" e il controllo ripassa al programma. Ovviamente quello che misureresti è l'intervallo tra l'ultima interruzione avvenuta e quando il carattere, finalmente decodificato e tradotto, viene passato al programma.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
OK, ora ci metto le mani e poi ti faccio sapere..per ora sei stato prezioso..thx
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
Rieccomi qui!
Il file che tu dici pc_keyb.c l' ho beccato ed anche la funzione keyboard_interrupt(). La riporto: static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) { #ifdef CONFIG_VT kbd_pt_regs = regs; #endif spin_lock_irq(&kbd_controller_lock); handle_kbd_event(); spin_unlock_irq(&kbd_controller_lock); } OK, guardando questo codice si nota che la gestione di un Interrupt di tastiera è gestito dalla funzione handle_kbd_event(), che come dice il nome è il "gestore" degli eventi Keyboard. Le funzioni spin_lock_irq(&kbd_controller_lock) e spin_unlock_irq(&kbd_controller_lock) mi pare servano a bloccare il keyboard controller affinchè non pervengano altre interruzioni. Anche qui i conti tornano: essendo un collegamento seriale, il controller deve trattare un tasto alla volta. Però correggimi se sbaglio... Tornando alla handle_kbd_event(), si nota questo codice: if (status & KBD_STAT_MOUSE_OBF) handle_mouse_event(scancode); else handle_keyboard_event(scancode); dal quale si capisce che la funzione tratta anche il mouse. ...bisogna entrare in quella specifica della tastiera....Entriamoci dunque.. static unsigned char kbd_exists = 1; static inline void handle_keyboard_event(unsigned char scancode) { #ifdef CONFIG_VT kbd_exists = 1; if (do_acknowledge(scancode)) handle_scancode(scancode, !(scancode & 0x80)); #endif tasklet_schedule(&keyboard_tasklet); } Bene! E se ora io piazzo le letture del time in questa funzione? Uso una rdtsc o una gettimeofday() . La questione è che la gestione dell' IRQ è comunque iniziata nelle funzioni precedenti e quel tempo non lo posso buttare. io direi di leggere il time nelle funzioni precedenti e poi, se è il mouse ad aver generato l' IRQ, butto tutto, altrimenti mi prendo quello che volevo. Ti pare corretto ? Ciao |
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
sì
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
Ahò! ma è un forum o una chat? Come hai fatto a rispondermi nel giro di un min?
Dunque il tempo lo prendo in maniera simile: if (status & KBD_STAT_MOUSE_OBF) handle_mouse_event(scancode); else { int inizio = gettimeofday(); handle_keyboard_event(scancode); int fine = gettimeofday(); proc_var = fine - inizio; } Ovviamente è un meta-linguaggio... |
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Chi o che cosa ti ha messo in testa che in kernel space puoi usare le funzioni delle glibc (tipo gettimeofday)?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
OK...sorry... procedo con l' "ignorantissima" rdtsc corretto questo, la procedura è giusta no? |
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
O rdtsc oppure do_gettimeofday (v. linux/time.h -- credo che sia invocabile anche in irq context)
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
OK ora provo.
grazie |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 18:57.



















