Gestione in ingresso e in uscita
Questo argomento fornisce un'introduzione alle considerazioni di programmazione per la gestione di input e output e le subroutine di gestione dell'input e dell'output (I/O).
Le subroutine della libreria I/O possono inviare dati a o da dispositivi o file. Il sistema tratta i dispositivi come se fossero file I/O. Ad esempio, è necessario anche aprire e chiudere un dispositivo proprio mentre si fa un file.
Alcune subroutine utilizzano input standard e output standard come i loro canali I/O. Per la maggior parte delle subroutine, tuttavia, è possibile specificare un file diverso per la sorgente o la destinazione del trasferimento dati. Per alcune subroutine è possibile utilizzare un puntatore di file ad una struttura che contiene il nome del file; per altri è possibile utilizzare un descrittore di file (cioè il numero intero positivo assegnato al file quando viene aperto).
#include <stdio.h>Alcune delle subroutine della libreria I/O sono macro definite in un file di intestazione e alcuni sono moduli oggetto di funzioni. In molti casi la libreria contiene una macro e una funzione che fanno lo stesso tipo di operazione. Considerare quanto segue quando si decide se utilizzare la macro o la funzione:
- Non è possibile impostare un breakpoint per una macro utilizzando il programma dbx .
- Le macro sono di solito più veloci delle loro funzioni equivalenti perché il preprocessore sostituisce le macro con linee effettive di codice nel programma.
- I macro risultano in codice oggetto più grande dopo essere stati compilati.
- Le funzioni possono avere effetti collaterali da evitare.
I file, i comandi e le subroutine utilizzati nella gestione I/O forniscono le seguenti interfacce:
- Basso livello
- L'interfaccia di basso livello fornisce funzioni di apertura e chiusura di base per file e dispositivi.
- Flusso
- L'interfaccia di flusso fornisce I/O di lettura e scrittura per tubi e FIFOs.
- Terminale
- L'interfaccia terminale fornisce output formattato e tamponamento.
- Asincrono
- L'interfaccia asincrona fornisce I/O e elaborazione simultanee.
- Lingua di input
- L'interfaccia in ingresso in ingresso utilizza i comandi lex e yacc per generare un analizzatore lessicale e un programma di parser per l'interpretazione I/O.
Interfacce I/O di basso livello
Le interfacce I/O di basso livello sono punti di ingresso diretti in un kernel, fornendo funzioni come l'apertura dei file, la lettura e la scrittura da file, e la chiusura dei file.
Il comando line fornisce l'interfaccia che consente di leggere una riga dall'input standard e le seguenti subroutine forniscono altre funzioni I/O di basso livello:
- aperto, openx o creat
- Preparare un file, o altro oggetto di percorso, per la lettura e la scrittura tramite un descrittore di file assegnato
- lettura, readx, readv o readvx
- Leggi da un descrittore di file aperto
- scrittura, writex, writev o writevx
- Scrivi su un descrittore di file aperto
- Chiudi
- Relinquina un descrittore di file
Le subroutine open e creat impostano le voci in tre tabelle di sistema. Un descrittore di file indicizza la prima tabella, che funziona come un'area dati di processo a cui è possibile accedere tramite le subroutine di lettura e scrittura. Ogni voce in questa tabella ha un puntatore ad una voce corrispondente nella seconda tabella.
La seconda tabella è un database per sistema, o tabella di file, che consente di condividere un file aperto tra diversi processi. Le voci in questa tabella indicano se il file era aperto per la lettura, la scrittura o come un tubo, e quando il file è stato chiuso. C'è anche un offset per indicare dove avrà luogo la prossima lettura o scrittura e un puntatore finale per indicare l'ingresso alla terza tabella, che contiene una copia dell'i-node del file.
La tabella dei file contiene voci per ogni istanza di una sottoroutine aperta o create sul file, ma la tabella i-node contiene una sola voce per ogni file.
Quando si verifica un'operazione di lettura o scrittura, gli argomenti dell'utente e la voce della tabella dei file vengono utilizzati per impostare le seguenti variabili:
- Indirizzo utente dell'area di destinazione I/O
- Conteggio byte per il trasferimento
- Posizione corrente nel file
Se il file di cui si fa riferimento è un file speciale di tipo carattere, la sottoroutine di lettura o scrittura appropriata è chiamata a trasferire i dati, oltre ad aggiornare il conteggio e la posizione attuale. In caso contrario, la posizione corrente viene utilizzata per calcolare un numero di blocco logico nel file.
Se il file è un file ordinario, il numero di blocco logico deve essere mappato ad un numero di blocco fisico. Non è necessario mappare un file speciale di tipo di blocco. Il numero di blocco fisico risultante viene utilizzato per leggere o scrivere il dispositivo appropriato.
I driver del dispositivo di blocco possono fornire la possibilità di trasferire le informazioni direttamente tra l'immagine core dell'utente e il dispositivo in blocchi di dimensioni più grandi delle richieste del chiamante senza utilizzare buffer. Il metodo implica l'impostazione di un file speciale di tipo di carattere corrispondente alla periferica raw e fornire sottoroutine di lettura e scrittura per creare un'intestazione di buffer privata, non condivisa con le informazioni appropriate. Possono essere fornite delle subroutine aperte e vicine e una sottoroutine a funzione speciale può essere chiamata per il nastro magnetico.
Interfacce I/O di flusso
Le interfacce I/O di flusso forniscono i dati come un flusso di byte che non viene interpretato dal sistema, che offre un'implementazione più efficiente per i protocolli di networking rispetto all'elaborazione delle I/O dei caratteri. Non esistono confini record quando si legge e si scrive utilizzando I/O di flusso. Ad esempio, un processo di lettura di 100 bytes da un tubo non può determinare se il processo che ha scritto i dati nel tubo ha fatto una sola scrittura di 100 bytes, o due scritture di 50 bytes, o anche se il 100 bytes proviene da due diversi processi.
Stream I/Os può essere pipe o FIFOs (first-in, file di prima uscita). I FIFOs sono simili ai tubi perché permettono ai dati di fluire solo in un modo (da sinistra a destra). Tuttavia, a un FIFO può essere dato un nome e si può accedere da processi indipendenti, diversamente da un tubo. FIFOs sono a volte indicati come named pipe. Poiché ha un nome, è possibile aprire una FIFO utilizzando la sottoroutine I/O fopen standard. Per aprire un pipe è necessario chiamare la sottoroutine pipe , che restituisce un descrittore di file, e la sottoroutine I/O fdopen standard per associare un descrittore di file aperto con un flusso I/O standard.
Si accede alle interfacce I/O di flusso attraverso le seguenti sottoroutine e macro:
- fclose
- Chiude un flusso
- fedi, ferrore, clearerr o fileno
- Controllare lo stato di un flusso
- fflush
- Scrivi tutti i caratteri attualmente tamponati da un flusso
- fapri, freopen o fdopen
- Aprire un flusso
- fread o fwrite
- Eseguire input binari
- fseek, rewind, ftell, fgetpos o fsetpos
- Riposiamo il puntatore del file di un flusso
- getc, fgetc, getchar o getw
- Ottenere un carattere o una parola da un flusso di input
- gets o fgets
- Ottire una stringa da un flusso
- getwc, fgetwc o getwchar
- Ottenere un carattere ampio da un flusso di input
- getws o fgetws
- Ottire una stringa da un flusso
- printf, fprintf, sprintf, wsprintf, vprintf, vfprintf, vsprintf o vwsprintf
- Emissione formattata di stampa
- putc, putchar, fputc o putw
- Scrivi un carattere o una parola a un flusso
- mette o finserisce
- Scrivi una stringa a un flusso
- putwc, putwchar o fputwc
- Scrivi un carattere o una parola a un flusso
- putti o fputti
- Scrivi una stringa di carattere ampio a un flusso
- scanf, fscanf, sscanf o wsscanf
- Convertire input formattati
- setbuf, setvbuf, setbuffer o setlinebuf
- Assegnare il buffering a un flusso
- ungetc o ungetwc
- Spingere un carattere indietro nel flusso di input
Interfacce I/O del terminale
Le interfacce I/O terminali funzionano tra un processo e il kernel, fornendo funzioni quali buffering e output formattati. Ogni terminale e pseudo - terminale ha una struttura tty che contiene l'attuale ID gruppo di processo. Questo campo identifica il gruppo di processo per ricevere i segnali associati al terminale. È possibile accedere alle interfacce I/O del terminale tramite il comando iostat , che monitora il caricamento del dispositivo di sistema I/O e il daemon uprintfd , che consente di scrivere i messaggi del kernel sulla console di sistema.
Le caratteristiche terminali possono essere abilitate o disabilitate attraverso le seguenti sottoroutine:
- cfgetospeed, cfsetospeed, cfgetispeedo cfsetispeed
- Ottenere e impostare i tassi di baud di input e output
- ioctl
- Esegue funzioni di controllo associate al terminale
- termdef
- Query delle caratteristiche del terminale
- tcdrain
- Attese per l'output da completare
- tcflow
- Esegue funzioni di controllo del flusso
- tcflush
- Elimina i dati dalla coda specificata
- tcgetpgrp
- Ottiene ID gruppo di processo foreground
- tcsendbreak
- Invia una pausa su una linea di dati seriale asincrona
- tcsetattr
- Imposta stato terminale
- ttylock, ttywait, ttyunlocko ttylock
- Funzioni di blocco tty di controllo
- ttyname o isatty
- Porta il nome di un terminale
- ttyslot
- Trova lo slot nel file utmp per l'utente corrente
Interfacce I/O asincrone
Le subroutine I/O asincrone consentono ad un processo di avviare un'operazione di I/O e di avere la subroutine di ritorno subito dopo l'avvio dell'operazione o la coda. Un'altra sottoroutine è tenuta ad attendere che l'operazione venga completata (o tornare immediatamente se l'operazione è già terminata). Ciò significa che un processo può sovrapporsi alla sua esecuzione con il suo I/O I/O o sovrapposizione tra diversi dispositivi. Anche se l'I/O asincrono non migliora sensibilmente le prestazioni per un processo che sta leggendo da un file disco e la scrittura su un altro file disco, l'I/O asincrono può fornire notevoli miglioramenti delle prestazioni per altri tipi di programmi di I/O, come i programmi che scaricano un disco su un nastro magnetico o visualizzano un'immagine su un display dell'immagine.
Sebbene non richiesto, un processo che sta eseguendo I/O asincroni può dire al kernel di notificarlo quando un descrittore specificato è pronto per l'I/O (chiamato anche I/O - driven I/O). Quando si utilizza LEGACY AIO, il kernel notifica il processo dell'utente con il segnale SIGIO. Quando si utilizza POSIX AIO, la struttura sigevent viene utilizzata dal programmatore per determinare quale segnale per il kernel utilizzare per notificare il processo utente. I segnali includono SIGIO, SIGUSR1e SIGUSR2.
Per utilizzare I/O asincroni, un processo deve effettuare le seguenti operazioni:
- Stabilire un gestore per il segnale SIGIO . Questo passo è necessario solo se viene richiesta la notifica da parte del segnale.
- Impostare l'ID di processo o l'ID del gruppo di processo per ricevere i segnali SIGIO . Questo passo è necessario solo se viene richiesta la notifica da parte del segnale.
- Abilitare I/O asincroni. L'amministratore di sistema di solito determina se l'I/O asincrono viene caricato (abilitato). L'abilitazione si verifica alla startup del sistema.
Vengono fornite le seguenti subroutine I/O asincrone:
- aio_annullo
- Annulla una o più richieste I/O asincrone in sospeso
- aio_errore
- Richiama lo stato di errore di una richiesta I/O asincrona
- aio_fsync
- Sincronizza i file asincroni.
- aio_nwait
- Sospende il processo di chiamata fino a quando non viene completato un certo numero di richieste I/O asincrone.
- aio_letti
- Letture asincrone da un descrittore di file
- aio_return
- Richiama lo stato di ritorno di una richiesta I/O asincrona
- aio_sospendi
- Sospende il processo di chiamata fino al completamento di una o più richieste I/O asincrone
- aio_scrittura
- Scrive in modo asincrono su un descrittore di file
- lio_elenio
- Iniziate un elenco di richieste I/O asincrone con una sola chiamata
- poll o selezionare
- Controllare lo stato I/O di più descrittori di file e code di messaggi
Per l'utilizzo con la sottoroutine poll vengono forniti i seguenti file di intestazione:
- poll.h
- Definisce le strutture e le bandiere utilizzate dalla subroutine poll
- aio.h
- Definisce la struttura e gli indicatori utilizzati dalle sottoroutine aio_read, aio_writee aio_sospendere