Pagina 2 di 2 primaprima 1 2
Visualizzazione dei risultati da 11 a 17 su 17
  1. #11
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305
    Quote Originariamente inviata da M.A.W. 1968 Visualizza il messaggio
    Codesto testo (Deitel?) finisce per confonderti solo le idee, specialmente a causa della traduzione piuttosto approssimativa.

    Il buffer al quale si riferiscono le slide che hai referenziato è il buffer di tastiera gestito dal BIOS (nei PC standard trattasi di una coda circolare gestita tramite due puntatori nell'area dati del BIOS) che sta a monte dello standard input, in quella lunga catena della quale si accennava sopra.

    Viceversa, il buffer della getchar() è un buffer interno alla libreria di runtime: come ogni buffer di tale categoria, è qualcosa che si frappone tra il file di input (in questo caso stdin, che è comunque un "file" per il sistema operativo e per il linguaggio C) e il programma stesso. In definitiva, si parla di due distinti buffer, con meccanismi di gestione diversi, a carico di entità ben distinte.

    Ribadisco, per maggior chiarezza: quando si parla di buffered input per le funzioni di libreria come getchar(), ci si riferisce al buffer interno alla libreria e in particolare alla necessità di terminare ciascun input con ENTER.
    ok almeno questo mi é chiaro. ma in breve quello che succede e che il progrAmma si sospende quando invoco getchar, i tastinpremuti vengono caricati dal buffer della tastiera(quello doppia coda circolar) allo stdin e dallo stdin la getchar li legge e li mette nel proprio buffer e li fornisce al programma??
    potresti spoegarmi a grosse linee il procedimento ? grazie

  2. #12
    Quote Originariamente inviata da linux_r Visualizza il messaggio
    ok almeno questo mi é chiaro. ma in breve quello che succede e che il progrAmma si sospende quando invoco getchar, i tastinpremuti vengono caricati dal buffer della tastiera(quello doppia coda circolar) allo stdin e dallo stdin la getchar li legge e li mette nel proprio buffer e li fornisce al programma??
    potresti spoegarmi a grosse linee il procedimento ? grazie
    Dopo aver chiarito i dubbi fondamentali, possiamo provare a schematizzare il percorso con un esempio di base, relativo all'originale PC AT IBM. Al giorno d'oggi alcuni dettagli sono profondamente mutati, ma i concetti di retrocompatibilità rimangono del tutto invariati.
    Tutti i valori esemplificativi sono esadecimali.

    L'operazione avviene sostanzialmente in due tempi.
    Premendo un tasto (ad esempio "P") sulla tastiera, il microcontroller ivi contenuto (in origine un Intel 8031) invia sulla connessione seriale il valore Kscan 4Dh. All'altro capo della connessione, nel design AT originale, c'era un controller dedicato 8042 che effettuava una prima "traduzione" del valore, mappando 4Dh su 19h. Tale controller genera quindi un interrupt hardware, che a sua volta invoca l'handler INT 9h del BIOS, il quale legge il valore 19h dal buffer (hardware) interno al controller 8042 e lo trasforma ulteriormente, in questo caso nel codice ASCII 70h ovvero "p" (se nessuno SHIFT è stato premuto e CAPS LOCK non è attivo). Tale valore viene, sempre a carico di INT 9h, inserito nel buffer a coda circolare a 16 entries nell'area dati del BIOS, accompagnato dal relativo scan code 19h. Qui termina la prima fase dell'operazione.

    In un secondo momento, il sistema operativo (o software applicativo con idonei diritti) usa tipicamente INT 16h, altra funzione BIOS, per determinare se vi sono tasti nel buffer di tastiera. Un'apposita sottofunzione verifica se il buffer è non-vuoto (i due puntatori di inizio e fine, in tale caso, non sono coincidenti) e preleva il più vecchio codice ivi inserito: nel nostro caso, il valore a 16 bit 1970h. Tale funzione inoltre aggiorna i puntatori, il che rende nuovamente disponibili le locazioni usate dal tasto appena "prelevato".
    Da qui in poi, il codice tasto sottoposto alle varie trasformazioni (bisognerebbe parlare ad esempio di nazionalizzazione ed ASCII esteso, eccetera) viene generalmente reso disponibile dal DOS su stdio, se non stiamo parlando di applicazioni verticali o altri casi particolari. E qui entra finalmente in gioco la funzione getchar() col suo bravo buffer.

    A rigore, occorrerebbe inoltre parlare del secondo scancode inviato dal controller di tastiera al momento del rilascio del tasto. Tale scancode è caratterizzato dal bit 7 alto, ma nella generalità dei casi viene scartato a livello del controller di tastiera (da molti anni integrato nel chipset) e/o di INT 9h BIOS.

    Questo, con numerose omissioni e qualche approssimazione, è in termini generali il percorso dei codici, dal controller di tastiera fino al flusso di input del terminale gestito a livello di SO.
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  3. #13
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305
    Quote Originariamente inviata da M.A.W. 1968 Visualizza il messaggio
    Dopo aver chiarito i dubbi fondamentali, possiamo provare a schematizzare il percorso con un esempio di base, relativo all'originale PC AT IBM. Al giorno d'oggi alcuni dettagli sono profondamente mutati, ma i concetti di retrocompatibilità rimangono del tutto invariati.
    Tutti i valori esemplificativi sono esadecimali.

    L'operazione avviene sostanzialmente in due tempi.
    Premendo un tasto (ad esempio "P") sulla tastiera, il microcontroller ivi contenuto (in origine un Intel 8031) invia sulla connessione seriale il valore Kscan 4Dh. All'altro capo della connessione, nel design AT originale, c'era un controller dedicato 8042 che effettuava una prima "traduzione" del valore, mappando 4Dh su 19h. Tale controller genera quindi un interrupt hardware, che a sua volta invoca l'handler INT 9h del BIOS, il quale legge il valore 19h dal buffer (hardware) interno al controller 8042 e lo trasforma ulteriormente, in questo caso nel codice ASCII 70h ovvero "p" (se nessuno SHIFT è stato premuto e CAPS LOCK non è attivo). Tale valore viene, sempre a carico di INT 9h, inserito nel buffer a coda circolare a 16 entries nell'area dati del BIOS, accompagnato dal relativo scan code 19h. Qui termina la prima fase dell'operazione.

    In un secondo momento, il sistema operativo (o software applicativo con idonei diritti) usa tipicamente INT 16h, altra funzione BIOS, per determinare se vi sono tasti nel buffer di tastiera. Un'apposita sottofunzione verifica se il buffer è non-vuoto (i due puntatori di inizio e fine, in tale caso, non sono coincidenti) e preleva il più vecchio codice ivi inserito: nel nostro caso, il valore a 16 bit 1970h. Tale funzione inoltre aggiorna i puntatori, il che rende nuovamente disponibili le locazioni usate dal tasto appena "prelevato".
    Da qui in poi, il codice tasto sottoposto alle varie trasformazioni (bisognerebbe parlare ad esempio di nazionalizzazione ed ASCII esteso, eccetera) viene generalmente reso disponibile dal DOS su stdio, se non stiamo parlando di applicazioni verticali o altri casi particolari. E qui entra finalmente in gioco la funzione getchar() col suo bravo buffer.

    A rigore, occorrerebbe inoltre parlare del secondo scancode inviato dal controller di tastiera al momento del rilascio del tasto. Tale scancode è caratterizzato dal bit 7 alto, ma nella generalità dei casi viene scartato a livello del controller di tastiera (da molti anni integrato nel chipset) e/o di INT 9h BIOS.

    Questo, con numerose omissioni e qualche approssimazione, è in termini generali il percorso dei codici, dal controller di tastiera fino al flusso di input del terminale gestito a livello di SO.
    ti ringrazio per questi dettagli implementativi.. davvero grazie .. ma quindi sintetizzando a grosse linee lo schema é:
    premo i tastindella tastiera , e incorrispondenti valori vengono caricati nel buffer di quest ultima , dopo aver premuto il tasti enter vengono inseriti nel flusso stdin (quindi vengono resi disponibili per l' input) e dall ' input la getchar li carica nel buffer esatto?

  4. #14
    Quote Originariamente inviata da linux_r Visualizza il messaggio
    ti ringrazio per questi dettagli implementativi.. davvero grazie .. ma quindi sintetizzando a grosse linee lo schema é:
    premo i tastindella tastiera , e incorrispondenti valori vengono caricati nel buffer di quest ultima , dopo aver premuto il tasti enter vengono inseriti nel flusso stdin (quindi vengono resi disponibili per l' input) e dall ' input la getchar li carica nel buffer esatto?
    No. La pressione di ENTER è gestita unicamente a livello del buffer di getchar(): tanto è vero che esistono funzioni di libreria unbuffered, come appunto getch().
    L'inserimento dei singoli tasti nel flusso stdin è del tutto indipendente dalla presenza di ENTER (ci mancherebbe!): è solo il buffer finale nella libreria di runtime del C che fa da "tampone" ai dati da stdin e li mette a disposizione del programma unicamente dopo la pressione di ENTER.
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  5. #15
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305
    ok .. peró in questo caso nelle slide postate prime o c'é un errore o le
    ho interpretate male io. se dai un' pcchiata mostra che dopo la pressione di enter vengono caricate dal buffer bios nel flusso stdin . e da li getchar preleva i caratteri non mostra altri buffer

  6. #16
    È una visione molto semplificata e, per i sistemi operativi moderni, errata. Tra la pressione del tasto e la getch()/getchar() ci passa una marea di astrazioni intermedie che a te non devono interessare.

    Il modo più semplice di pensare la questione su un sistema moderno come Linux o Windows NT-like secondo me è questo:
    • quando viene premuto un tasto, tramite infinite magie che a te non interessano (interrupt che notifica il driver di tastiera, conversione scancode=>carattere, eventuale giro per le input queue del window manager, dispatch alla finestra corretta, scrittura nell'stdin del programma e chi più ne ha più ne metta) questo "atterra" dentro al buffer del sistema operativo relativo allo standard input del tuo processo, e lì rimane;
    • quando tu chiami la getchar(), la libreria C in primo luogo verifica se ci sono caratteri nel buffer tenuto dalla libreria standard (che sta a valle di quello del sistema operativo), e se c'è qualcosa pesca il carattere da restituire da lì;
    • se il buffer è vuoto, cerca di riempirlo; per fare ciò, prova a leggere dal buffer del sistema operativo (con una read su sistemi POSIX o con ReadFile su sistemi Windows); normalmente si tratta di una chiamata bloccante - se nel buffer del sistema operativo c'è qualcosa questo viene restituito, altrimenti si ferma tutto finché non arrivano caratteri. Una volta che il buffer della libreria C è stato ri-riempito, torna al passo precedente.

    In tutto questo ad un qualche livello (che dipende dal sistema operativo/dalla CRT/...) rientra anche il line-buffering, ovvero il fatto che vengono rese disponibili all'stdin del programma C solo righe intere.
    Tutte le eccezioni a questo funzionamento (input non bloccante, lettura da terminale senza echo, lettura senza line-buffering, ...) si ottengono normalmente con meccanismi platform-specific (ioctl/sequenze di escape/... su POSIX, API di console su Windows).
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #17
    Quote Originariamente inviata da linux_r Visualizza il messaggio
    ok .. peró in questo caso nelle slide postate prime o c'é un errore o le
    ho interpretate male io. se dai un' pcchiata mostra che dopo la pressione di enter vengono caricate dal buffer bios nel flusso stdin . e da li getchar preleva i caratteri non mostra altri buffer
    Sicuramente quelle dispense sono molto schematiche e semplificate, non entrano nel merito della reale implementazione della libreria di runtime del C e delle relazioni con il sistema operativo.
    Come regola generale, la generica documentazione online, anche creata ai fini didattici, è sempre da prendere con le molle. Di certo tali comportamenti sono approfonditi in ben altra maniera nella letteratura cartacea di riferimento(vedi ad esempio la prima decina di entries della sezione B).

    In genere le librerie dei compilatori C sono scritte in modo molto segregato rispetto al SO e non vanno a bypassare le varie API o Syscall, in questo caso accedendo direttamente al BIOS buffer: questo è il principio guida da tenere sempre presente in fase di apprendimento.

    Di norma la getchar() è poco più che una macro, la quale si limita a richiamare la generica getc() passandole stdin come file handle: poiché quest'ultima funzione è in grado di operare su qualsiasi file, di primo acchito non devi immaginare speciali capacità di accesso al BIOS keyboard buffer o altro, perché a questo livello non è neppure utile entrare in simili dettagli. A livello di descrizione logica e funzionale, parlando di getchar(), lo stdin deve ritenersi un file già formato a cura del sistema operativo: in effetti è didatticamente molto utile fare sempre mente locale al caso parallelo in cui lo stdin provenga effettivamente da un file di testo, con una banale redirezione da command line.

    In realtà i dettagli e le possibili varianti, come già accennato, sono molto numerosi e dovremmo andare a distinguere cosa avviene realmente sui vari DOS, Windows, GNU/linux, *BSD, brand unix vari, VMS e molto altro, distinguendo inoltre le varie implementazioni di libreria (Dinkum o piuttosto Digital Mars, Borland, Open Watcom, GCC, quindi ambienti portability oriented vs. verticalizzazioni dedicate, eccetera).

    Quello qui illustrato è lo schema logico-gerarchico e funzionale più corretto, sufficiente ad una comprensione di base del meccanismo. Per il resto, avrai tempo e modo di studiare come sono implementate le varie chiamate nei numerosi compilatori che rendono disponibili i sorgenti delle loro librerie.

    EDIT: cross-post con il buon MItaly.
    Ultima modifica di M.A.W. 1968; 10-05-2014 a 12:58
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.