Apa perbedaan antara deskriptor file dan penunjuk file?

Jawaban:

144

Deskriptor file adalah "pegangan" integer tingkat rendah yang digunakan untuk mengidentifikasi file yang dibuka (atau soket, atau apa pun) di tingkat kernel, di Linux dan sistem mirip Unix lainnya.

Anda meneruskan deskriptor file "polos" ke panggilan Unix yang sebenarnya, seperti read(), write()dan sebagainya.

Sebuah FILEpointer adalah konstruksi tingkat perpustakaan standar C, digunakan untuk merepresentasikan file. The FILEmembungkus file descriptor, dan menambahkan buffering dan fitur lain untuk membuat I / O lebih mudah.

Anda meneruskan FILEpointer ke fungsi C standar seperti fread()dan fwrite().

beristirahat
sumber
@nvl: fildes pasti tersedia untuk Windows, misalnya msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm
2
@unwind Apa yang Anda maksud dengan deskriptor file "telanjang"? Referensi terkait mengatakan bahwa fdargumen pertama untuk read(). Mengapa Anda menyebutnya telanjang?
Geek
3
@Geek Dibandingkan dengan jenis pustaka standar FILE *, deskriptor file integer adalah "kurang dibungkus", yaitu "telanjang".
bersantai
57

Salah satunya adalah buffered ( FILE *) dan yang lainnya tidak. Dalam praktiknya, Anda ingin menggunakan FILE *hampir selalu saat Anda membaca dari file 'asli' (yaitu di drive), kecuali Anda tahu apa yang Anda lakukan atau kecuali file Anda sebenarnya adalah soket atau lebih ..

Anda bisa mendapatkan deskriptor file dari FILE *penggunaan fileno()dan Anda bisa membuka buffer FILE *dari deskriptor file menggunakanfdopen()

Ben
sumber
12
+1 untuk menunjukkan fileno (), pengaturan halaman manual membuat yang satu ini sulit ditemukan. Sama untuk fdopen ().
BD di Rivenhill
20

Deskriptor file hanyalah bilangan bulat yang Anda peroleh dari open()panggilan POSIX . Menggunakan standar C fopen()Anda mendapatkan FILEstruct kembali. The FILEstruct berisi deskripsi file ini antara lain seperti akhir-of-file dan indikator kesalahan, posisi aliran dll

Jadi menggunakan fopen()memberi Anda sejumlah abstraksi dibandingkan dengan open(). Secara umum Anda harus menggunakan fopen()karena itu lebih portabel dan Anda dapat menggunakan semua fungsi C standar lainnya yang menggunakan FILEstruct, yaitu, fprintf()dan keluarga.

Tidak ada masalah kinerja saat menggunakannya.

Martin Wickman
sumber
8
1 untuk memunculkan portabilitas. FILE adalah bagian dari Library C Standar (kembali ke C89 / C90); deskriptor file tidak.
tomlogic
15

Deskriptor file vs Penunjuk file

Deskriptor file:

File Descriptor adalah nilai integer yang dikembalikan oleh open()panggilan sistem.

int fd = open (filePath, mode);

  1. Penangan level rendah / kernel.
  2. lulus untuk membaca () dan menulis () dari Panggilan Sistem UNIX.
  3. Tidak termasuk buffering dan fitur semacam itu.
  4. Kurang portabel dan kurang efisiensi.

Penunjuk file:

Penunjuk File adalah penunjuk ke struktur C yang dikembalikan oleh fopen()fungsi pustaka, yang digunakan untuk mengidentifikasi file, membungkus deskriptor file, fungsi buffering, dan semua fungsi lain yang diperlukan untuk operasi I / O. Penunjuk file berjenis FILE , yang definisinya dapat ditemukan di "/usr/include/stdio.h" . Definisi ini mungkin berbeda dari satu kompilator ke kompiler lainnya.

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. Ini adalah antarmuka tingkat tinggi.
  2. Diteruskan ke fungsi fread () dan fwrite ().
  3. Termasuk buffering, indikasi kesalahan dan deteksi EOF, dll.
  4. Memberikan portabilitas dan efisiensi yang lebih tinggi.
Yogeesh HT
sumber
1
Apakah Anda dapat mendukung klaim efisiensi yang lebih tinggi itu? Saya belum pernah mendengarnya.
Gid
1
Klaim "efisiensi" bisa jadi karena buffering. Dengan deskriptor file, setiap read () atau write () adalah syscall, dan setiap syscall harus dianggap mahal. Dengan FILE *, buffering berarti beberapa operasi baca dan tulis tidak akan menjadi syscall.
Mike Spear
12

Ingin menambahkan poin yang mungkin berguna.

TENTANG FILE *

  1. tidak dapat digunakan untuk komunikasi antarproses (IPC).
  2. gunakan saat Anda membutuhkan I / O dengan buffer tujuan umum. (printf, frpintf, snprintf, scanf)
  3. Saya menggunakannya berkali-kali untuk log debug. contoh,

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

TENTANG FILE DESCRIPTOR

  1. Ini umumnya digunakan untuk IPC.

  2. Memberikan kontrol tingkat rendah ke file di sistem * nix. (Perangkat, file, soket, dll), sehingga lebih kuat daripada FILE *.

Akshay Patil
sumber
Tidak bisakah Anda menggunakan fdopen()untuk melakukan hal-hal seperti IPC dan perangkat dengan FILE*?
osvein
Sebenarnya, ya dan tidak. Anda tidak dapat menyiapkan dan menginisialisasi IPC dengan FILE*, tetapi Anda dapat membuat FILE*dari deskriptor file ( fdopen()) dan menutupnya nanti juga FILEakan menutup deskriptor. Oleh karena itu, Anda dapat melakukan IPC, tetapi Anda harus berurusan dengan deskriptor file sedikit untuk memfasilitasi IPC langsung.
Mikha W
3

FILE *lebih berguna ketika Anda bekerja dengan file teks dan user input / output, karena memungkinkan Anda untuk menggunakan fungsi API seperti sprintf(), sscanf(), fgets(), feof()dll

API deskriptor file adalah level rendah, sehingga memungkinkan untuk bekerja dengan soket, pipa, file yang dipetakan memori (dan file biasa, tentu saja).

qrdl
sumber
1
+1 karena Anda menambahkan file yang dipetakan memori, karena pada pembacaan saya saat ini, jawaban lain telah diberikan.
ernie.cordell
3

Sekadar catatan untuk menyelesaikan diskusi (jika tertarik) ....

fopenbisa jadi tidak aman, dan Anda mungkin harus menggunakan fopen_satau opendengan kumpulan bit eksklusif. C1X menawarkan xmode, sehingga Anda dapat fopendengan mode "rx", "wx", dll

Jika Anda menggunakan open, Anda mungkin mempertimbangkan open(..., O_EXCL | O_RDONLY,... )atau open(..., O_CREAT | O_EXCL | O_WRONLY,... ).

Lihat, sebagai contoh, Jangan membuat asumsi tentang fopen () dan pembuatan file .

jww
sumber
Karena fopen_stampaknya tidak tersedia dengan POSIX, saya berasumsi solusi yang paling portabel adalah untuk open(2)dan kemudian fdopen(2). (menyisihkan jendela). Juga, apa yang lebih cepat fopen_s()atau open(2)diikuti fdopen(2)?
Mihir
1

Panggilan sistem sebagian besar menggunakan deskriptor file, misalnya readdan write. Fungsi perpustakaan akan menggunakan penunjuk file ( printf, scanf). Namun, fungsi perpustakaan hanya menggunakan panggilan sistem internal.

Pavunkumar
sumber
Saya tidak yakin mengapa Anda mengatakan bahwa fungsi perpustakaan hanya menggunakan panggilan sistem internal: Jika yang Anda maksud adalah fungsi CI / O standar (atau yang lainnya dalam hal ini), saya tidak yakin itu (secara universal?) Benar. Jika tidak, bukan itu yang Anda katakan, jadi saya ingin bahasa di postingan Anda dibersihkan sedikit. Kalimat terakhir membuatku bingung.
ernie.cordell
1

Saya menemukan sumber daya yang bagus di sini , memberikan gambaran umum tingkat tinggi tentang perbedaan antara keduanya:

Ketika Anda ingin melakukan input atau output ke sebuah file, Anda memiliki dua pilihan mekanisme dasar untuk merepresentasikan koneksi antara program Anda dan file: deskriptor dan aliran file. Deskriptor file direpresentasikan sebagai objek bertipe int, sedangkan aliran direpresentasikan sebagai objek FILE *.

Deskriptor file menyediakan antarmuka tingkat rendah yang primitif untuk operasi input dan output. Baik deskriptor dan aliran file dapat mewakili koneksi ke perangkat (seperti terminal), atau pipa atau soket untuk berkomunikasi dengan proses lain, serta file normal. Tetapi, jika Anda ingin melakukan operasi kontrol yang khusus untuk jenis perangkat tertentu, Anda harus menggunakan deskriptor file; tidak ada fasilitas untuk menggunakan aliran dengan cara ini. Anda juga harus menggunakan deskriptor file jika program Anda perlu melakukan input atau output dalam mode khusus, seperti input nonblocking (atau polling) (lihat Bendera Status File).

Stream menyediakan antarmuka tingkat yang lebih tinggi, yang dilapisi di atas fasilitas deskriptor file primitif. Antarmuka aliran memperlakukan semua jenis file hampir sama — satu-satunya pengecualian adalah tiga gaya buffering yang dapat Anda pilih (lihat Stream Buffering).

Keuntungan utama menggunakan antarmuka aliran adalah bahwa serangkaian fungsi untuk melakukan operasi input dan output aktual (sebagai lawan operasi kontrol) pada aliran jauh lebih kaya dan lebih kuat daripada fasilitas terkait untuk deskriptor file. Antarmuka deskriptor file hanya menyediakan fungsi sederhana untuk mentransfer blok karakter, tetapi antarmuka aliran juga menyediakan fungsi masukan dan keluaran yang diformat kuat (printf dan scanf) serta fungsi untuk masukan dan keluaran berorientasi karakter dan garis.

Karena aliran diterapkan dalam hal deskriptor file, Anda dapat mengekstrak deskriptor file dari aliran dan melakukan operasi tingkat rendah langsung pada deskriptor file. Pada awalnya Anda juga dapat membuka koneksi sebagai deskriptor file, lalu membuat streaming yang terkait dengan deskriptor file tersebut.

Secara umum, Anda harus tetap menggunakan stream daripada deskriptor file, kecuali ada beberapa operasi tertentu yang ingin Anda lakukan yang hanya dapat dilakukan pada deskriptor file. Jika Anda seorang pemrogram pemula dan tidak yakin fungsi apa yang akan digunakan, kami sarankan Anda berkonsentrasi pada fungsi masukan yang diformat (lihat Input yang Diformat) dan fungsi keluaran yang diformat (lihat Output yang Diformat).

Jika Anda khawatir tentang portabilitas program Anda ke sistem selain GNU, Anda juga harus menyadari bahwa deskriptor file tidak portabel seperti streaming. Anda dapat mengharapkan sistem apa pun yang menjalankan ISO C untuk mendukung streaming, tetapi sistem non-GNU mungkin tidak mendukung deskriptor file sama sekali, atau mungkin hanya mengimplementasikan subset dari fungsi GNU yang beroperasi pada deskriptor file. Akan tetapi, sebagian besar fungsi deskriptor file dalam GNU C Library termasuk dalam standar POSIX.1.

Suraj Jain
sumber