Qual è la differenza tra un descrittore di file e un puntatore di file?


Risposte:


144

Un descrittore di file è un "handle" intero di basso livello utilizzato per identificare un file aperto (o socket, o qualsiasi altra cosa) a livello di kernel, in Linux e altri sistemi Unix-like.

Si passano descrittori di file "nudi" alle effettive chiamate Unix, come read(), write()e così via.

Un FILEpuntatore è un costrutto a livello di libreria standard C, utilizzato per rappresentare un file. Il FILEwrapping del descrittore di file e aggiunge buffering e altre funzionalità per rendere più facile l'I / O.

Si passano i FILEpuntatori a funzioni C standard come fread()e fwrite().


@nvl: Fildes è sicuramente disponibile per Windows, ad esempio msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm

2
@unwind Cosa intendevi per descrittori di file "nudi"? Il riferimento collegato dice che il fdè il primo argomento per read(). Perché lo chiami nudo?
Geek

3
@Geek Rispetto al FILE *tipo della libreria standard , il descrittore di file intero è "meno impacchettato", cioè "nudo".
rilassarsi il

57

Uno è bufferizzato ( FILE *) e l'altro no. In pratica, vuoi usare FILE *quasi sempre quando stai leggendo da un file 'reale' (cioè sul disco), a meno che tu non sappia cosa stai facendo oa meno che il tuo file non sia effettivamente un socket o giù di lì ..

Puoi ottenere il descrittore di file da FILE *using fileno()e puoi aprire un buffer FILE *da un descrittore di file usandofdopen()


12
+1 per evidenziare fileno (), l'organizzazione delle pagine man lo rende difficile da trovare. Lo stesso per fdopen ().
BD a Rivenhill

20

Un descrittore di file è solo un numero intero che ottieni dalla open()chiamata POSIX . Usando lo standard C fopen()ottieni FILEindietro una struttura. La FILEstruttura contiene questo descrittore di file tra le altre cose come la fine del file e l'indicatore di errore, la posizione del flusso ecc.

Quindi l'utilizzo fopen()ti dà una certa quantità di astrazione rispetto a open(). In generale dovresti usarlo fopen()poiché è più portabile e puoi usare tutte le altre funzioni C standard che usano la FILEstruttura, cioè, fprintf()e la famiglia.

Non ci sono problemi di prestazioni nell'utilizzo di entrambi.


8
+1 per aumentare la portabilità. FILE fa parte della libreria C standard (torna a C89 / C90); i descrittori di file non lo sono.
tomlogic

15

Descrittore di file vs puntatore di file

Descrittore di file:

File Descriptor è un valore intero restituito dalla open()chiamata di sistema.

int fd = open (filePath, mode);

  1. Gestore di livello basso / kernel.
  2. passa a read () e write () delle chiamate di sistema UNIX.
  3. Non include il buffering e tali funzionalità.
  4. Meno portatile e manca di efficienza.

Puntatore file:

File Pointer è un puntatore a una struttura C restituita dalla fopen()funzione di libreria, che viene utilizzata per identificare un file, avvolgere il descrittore di file, funzionalità di buffering e tutte le altre funzionalità necessarie per le operazioni di I / O. Il puntatore di file è di tipo FILE , la cui definizione può essere trovato in "/usr/include/stdio.h" . Questa definizione può variare da un compilatore all'altro.

FILE *fp = fopen (filePath, mode);

// A FILE Structure returned by fopen 
    typedef struct 
    {
        unsigned char   *_ptr;
        int     _cnt;
        unsigned char   *_base;
        unsigned char   *_bufendp;
        short   _flag;
        short   _file;
        int     __stdioid;
        char    *__newbase;
#ifdef _THREAD_SAFE
        void *_lock;
#else
        long    _unused[1];
#endif
#ifdef __64BIT__
        long    _unused1[4];
#endif /* __64BIT__ */
    } FILE;
  1. È un'interfaccia di alto livello.
  2. Passato alle funzioni fread () e fwrite ().
  3. Include buffering, indicazione di errore e rilevamento EOF, ecc.
  4. Fornisce maggiore portabilità ed efficienza.

1
Sei in grado di sostenere questa affermazione di maggiore efficienza? Non l'ho mai sentito.
Gid

1
L'affermazione di "efficienza" potrebbe essere dovuta al buffering. Con un descrittore di file, ogni read () o write () è una syscall, e ogni syscall dovrebbe essere considerata costosa. Con un FILE *, il buffering significa che alcune letture e scritture non saranno chiamate di sistema.
Mike Spear

12

Vuoi aggiungere punti che potrebbero essere utili.

DI FILE *

  1. non può essere utilizzato per la comunicazione tra processi (IPC).
  2. usalo quando hai bisogno di I / O bufferizzato per scopi generali (printf, frpintf, snprintf, scanf)
  3. Lo uso molte volte per i log di debug. esempio,

                 FILE *fp;
                 fp = fopen("debug.txt","a");
                 fprintf(fp,"I have reached till this point");
                 fclose(fp);

DI FILE DESCRIPTOR

  1. Viene generalmente utilizzato per IPC.

  2. Fornisce un controllo di basso livello ai file sui sistemi * nix (dispositivi, file, socket, ecc.), Quindi più potente del FILE *.


Non puoi usare fdopen()per fare cose come IPC e dispositivi con FILE*?
osvein

In realtà, sia sì che no. Non è possibile configurare e inizializzare IPC con FILE*, ma è possibile creare un FILE*da un descrittore di file ( fdopen()) e la successiva chiusura di FILEchiuderà anche il descrittore. Pertanto, puoi eseguire IPC, ma devi occuparti un po 'dei descrittori di file per facilitare qualsiasi IPC diretto.
Micah W

3

FILE *è più utile quando si lavora con i file di testo e user input / output, perché consente di utilizzare le funzioni API come sprintf(), sscanf(), fgets(), feof()etc.

L'API del descrittore di file è di basso livello, quindi consente di lavorare con socket, pipe, file mappati in memoria (e file normali, ovviamente).


1
+1 perché hai aggiunto file mappati in memoria, poiché alla mia lettura corrente, le altre risposte sono già state fornite.
ernie.cordell

3

Solo una nota per concludere la discussione (se interessati) ....

fopenpuò essere insicuro e probabilmente dovresti usare fopen_so opencon set di bit esclusivi. C1X sta offrendo xmodalità, in modo da poter fopencon i modi "rx", "wx"e così via

Se usi open, potresti considerare open(..., O_EXCL | O_RDONLY,... )o open(..., O_CREAT | O_EXCL | O_WRONLY,... ).

Vedere, ad esempio, Non fare supposizioni su fopen () e sulla creazione di file .


Dato fopen_sche non sembra essere disponibile con POSIX, presumo che l'anima più portatile sarebbe quella di open(2)e poi fdopen(2). (lasciando da parte le finestre). Inoltre, cosa sarebbe più veloce fopen_s()o open(2)seguito da fdopen(2)?
Mihir

1

Le chiamate di sistema utilizzano principalmente descrittori di file, ad esempio reade write. La funzione di libreria utilizzerà i puntatori di file ( printf, scanf). Tuttavia, le funzioni di libreria utilizzano solo chiamate di sistema interne.


Non sono sicuro del motivo per cui stai dicendo che le funzioni di libreria utilizzano solo chiamate di sistema interne: se intendi le funzioni standard CI / O (o qualsiasi altra per quella materia), non sono sicuro che sia (universalmente?) Vero. Altrimenti, non è quello che hai detto, quindi mi piacerebbe vedere la lingua nel tuo post ripulita un po '. L'ultima frase mi lascia perplesso.
ernie.cordell

1

Ho trovato una buona risorsa qui , fornendo una panoramica di alto livello delle differenze tra i due:

Quando si desidera eseguire l'input o l'output in un file, è possibile scegliere tra due meccanismi di base per rappresentare la connessione tra il programma e il file: descrittori di file e flussi. I descrittori di file sono rappresentati come oggetti di tipo int, mentre i flussi sono rappresentati come oggetti FILE *.

I descrittori di file forniscono un'interfaccia primitiva di basso livello per le operazioni di input e output. Sia i descrittori di file che i flussi possono rappresentare una connessione a un dispositivo (come un terminale) o una pipe o un socket per la comunicazione con un altro processo, nonché un file normale. Tuttavia, se si desidera eseguire operazioni di controllo specifiche per un particolare tipo di dispositivo, è necessario utilizzare un descrittore di file; non ci sono strutture per utilizzare i flussi in questo modo. È inoltre necessario utilizzare i descrittori di file se il programma deve eseguire l'input o l'output in modalità speciali, come l'input non bloccante (o con polling) (vedere Flag di stato del file).

I flussi forniscono un'interfaccia di livello superiore, sovrapposta alle funzionalità primitive del descrittore di file. L'interfaccia stream tratta tutti i tipi di file praticamente allo stesso modo, l'unica eccezione sono i tre stili di buffering che puoi scegliere (vedi Stream Buffering).

Il vantaggio principale dell'utilizzo dell'interfaccia stream è che l'insieme di funzioni per eseguire effettive operazioni di input e output (al contrario delle operazioni di controllo) sui flussi è molto più ricco e potente delle corrispondenti funzionalità per i descrittori di file. L'interfaccia del descrittore di file fornisce solo semplici funzioni per il trasferimento di blocchi di caratteri, ma l'interfaccia stream fornisce anche potenti funzioni di input e output formattati (printf e scanf), nonché funzioni per input e output orientati ai caratteri e alla riga.

Poiché i flussi sono implementati in termini di descrittori di file, è possibile estrarre il descrittore di file da un flusso ed eseguire operazioni di basso livello direttamente sul descrittore di file. È inoltre possibile aprire inizialmente una connessione come descrittore di file e quindi creare un flusso associato a tale descrittore di file.

In generale, dovresti continuare a usare flussi piuttosto che descrittori di file, a meno che non ci sia qualche operazione specifica che desideri fare che può essere eseguita solo su un descrittore di file. Se sei un programmatore principiante e non sei sicuro di quali funzioni utilizzare, ti suggeriamo di concentrarti sulle funzioni di input formattato (vedi Input formattato) e sulle funzioni di output formattato (vedi Output formattato).

Se sei preoccupato per la portabilità dei tuoi programmi su sistemi diversi da GNU, dovresti anche essere consapevole che i descrittori di file non sono portabili come gli stream. Ci si può aspettare che qualsiasi sistema che esegue ISO C supporti i flussi, ma i sistemi non GNU potrebbero non supportare affatto i descrittori di file, o potrebbero implementare solo un sottoinsieme delle funzioni GNU che operano sui descrittori di file. Tuttavia, la maggior parte delle funzioni del descrittore di file nella libreria GNU C sono incluse nello standard POSIX.1.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.