อะไรคือความแตกต่างระหว่างตัวอธิบายไฟล์และตัวชี้ไฟล์?


114

ฉันต้องการทราบความแตกต่างระหว่างตัวอธิบายไฟล์และตัวชี้ไฟล์

นอกจากนี้คุณจะใช้สถานการณ์ใดแทนอีกสถานการณ์หนึ่ง


คำตอบ:


144

File descriptor คือ "หมายเลขอ้างอิง" จำนวนเต็มระดับต่ำที่ใช้เพื่อระบุไฟล์ที่เปิด (หรือซ็อกเก็ตหรืออะไรก็ตาม) ที่ระดับเคอร์เนลใน Linux และระบบอื่น ๆ ที่คล้าย Unix

คุณผ่าน "เปล่า" อธิบายไฟล์โทรยูนิกซ์ที่เกิดขึ้นจริงเช่นread(), write()และอื่น ๆ

FILEชี้เป็นสร้างห้องสมุดระดับมาตรฐาน C, ใช้ในการแสดงไฟล์ FILEwraps อธิบายไฟล์และเพิ่มบัฟเฟอร์และคุณสมบัติอื่น ๆ ที่จะทำให้ I / O ได้ง่ายขึ้น

คุณผ่านFILEตัวชี้ไปยังฟังก์ชัน C มาตรฐานเช่นและfread()fwrite()


@nvl: fildes พร้อมใช้งานใน Windows อย่างแน่นอนเช่นmsdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm

2
@unwind คำอธิบายไฟล์ "เปล่า" หมายถึงอะไร? การอ้างอิงที่เชื่อมโยงบอกว่าfdเป็นอาร์กิวเมนต์แรกread()ของ ทำไมเรียกว่าเปล่า?
Geek

3
@Geek เมื่อเทียบกับFILE *ประเภทของไลบรารีมาตรฐานตัวอธิบายไฟล์จำนวนเต็มจะ "ห่อน้อยกว่า" นั่นคือ "เปล่า"
ผ่อนคลายใน

57

หนึ่งถูกบัฟเฟอร์ ( FILE *) และอีกอันไม่ใช่ ในทางปฏิบัติคุณต้องการใช้FILE *เกือบตลอดเวลาเมื่อคุณอ่านจากไฟล์ 'จริง' (เช่นในไดรฟ์) เว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่หรือเว้นแต่ว่าไฟล์ของคุณเป็นซ็อกเก็ตจริง ๆ ..

คุณสามารถรับ file descriptor จากการFILE *ใช้งานfileno()และคุณสามารถเปิดบัฟเฟอร์FILE *จาก file descriptor โดยใช้ไฟล์fdopen()


12
+1 สำหรับการชี้ไปที่ fileno () การจัดระเบียบของ man page ทำให้ค้นหาได้ยาก เหมือนกันสำหรับ fdopen ()
BD ที่ Rivenhill

20

ตัวอธิบายไฟล์เป็นเพียงจำนวนเต็มที่คุณได้รับจากการopen()เรียกPOSIX การใช้มาตรฐาน C fopen()คุณจะได้โครงสร้างFILEกลับคืนมา โครงสร้างFILEประกอบด้วยตัวอธิบายไฟล์นี้ท่ามกลางสิ่งอื่น ๆ เช่นจุดสิ้นสุดของไฟล์และตัวบ่งชี้ข้อผิดพลาดตำแหน่งสตรีมเป็นต้น

ดังนั้นการใช้จะช่วยให้คุณมีจำนวนหนึ่งของนามธรรมเมื่อเทียบกับfopen() open()โดยทั่วไปคุณควรใช้fopen()เนื่องจากเป็นแบบพกพามากกว่าและคุณสามารถใช้ฟังก์ชัน C มาตรฐานอื่น ๆ ทั้งหมดที่ใช้โครงสร้างFILEเช่นfprintf()และตระกูลได้

ไม่มีปัญหาด้านประสิทธิภาพการใช้งานอย่างใดอย่างหนึ่ง


8
+1 สำหรับการพกพา FILE เป็นส่วนหนึ่งของ Standard C Library (กลับไปที่ C89 / C90) ตัวอธิบายไฟล์ไม่ใช่
tomlogic

15

ตัวอธิบายไฟล์เทียบกับตัวชี้ไฟล์

ตัวอธิบายไฟล์:

File Descriptor คือค่าจำนวนเต็มที่ส่งคืนโดยการopen()เรียกระบบ

int fd = open (filePath, mode);

  1. ตัวจัดการระดับต่ำ / เคอร์เนล
  2. passe เพื่ออ่าน () และเขียน () ของ UNIX System Calls
  3. ไม่รวมบัฟเฟอร์และคุณสมบัติดังกล่าว
  4. พกพาน้อยลงและขาดประสิทธิภาพ

ตัวชี้ไฟล์:

ตัวชี้ไฟล์เป็นตัวชี้ไปยังโครงสร้าง C ที่ส่งคืนโดยfopen()ฟังก์ชันไลบรารีซึ่งใช้ในการระบุไฟล์การตัดคำอธิบายไฟล์ฟังก์ชันการบัฟเฟอร์และฟังก์ชันอื่น ๆ ทั้งหมดที่จำเป็นสำหรับการดำเนินการ I / Oตัวชี้ไฟล์เป็นประเภทFILEซึ่งมีคำจำกัดความ สามารถพบได้ใน"/usr/include/stdio.h" คำจำกัดความนี้อาจแตกต่างกันไปในแต่ละคอมไพเลอร์

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. เป็นอินเตอร์เฟซระดับสูง
  2. ส่งผ่านไปยังฟังก์ชัน fread () และ fwrite ()
  3. รวมถึงการบัฟเฟอร์การบ่งชี้ข้อผิดพลาดและการตรวจจับ EOF ฯลฯ
  4. ให้การพกพาและประสิทธิภาพที่สูงขึ้น

1
คุณสามารถสำรองข้อมูลการอ้างสิทธิ์ที่มีประสิทธิภาพสูงกว่านั้นได้หรือไม่? ฉันไม่เคยได้ยินมาก่อน
Gid

1
การอ้างสิทธิ์ "ประสิทธิภาพ" อาจเป็นเพราะการบัฟเฟอร์ ด้วย file descriptor ทุก read () หรือ write () คือ syscall และทุก syscall ควรคิดว่ามีราคาแพง ด้วย FILE * การบัฟเฟอร์หมายความว่าการอ่านและเขียนบางอย่างจะไม่เป็น syscall
Mike Spear

12

ต้องการเพิ่มคะแนนที่อาจเป็นประโยชน์

เกี่ยวกับ FILE *

  1. ไม่สามารถใช้สำหรับการสื่อสารระหว่างกระบวนการ (IPC)
  2. ใช้เมื่อคุณต้องการ I / O บัฟเฟอร์วัตถุประสงค์ทั่วไป (printf, frpintf, snprintf, scanf)
  3. ฉันใช้มันหลายครั้งสำหรับบันทึกการแก้ไขข้อบกพร่อง ตัวอย่าง,

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

เกี่ยวกับ FILE DESCRIPTOR

  1. โดยทั่วไปจะใช้สำหรับ IPC

  2. ให้การควบคุมระดับต่ำแก่ไฟล์ในระบบ * nix (อุปกรณ์ไฟล์ซ็อกเก็ต ฯลฯ ) จึงมีประสิทธิภาพมากกว่าไฟล์FILE *.


คุณใช้fdopen()ทำสิ่งต่างๆเช่น IPC และอุปกรณ์ด้วยFILE*ไม่ได้หรือ?
osvein

จริงๆแล้วทั้งใช่และไม่ใช่ คุณไม่สามารถตั้งค่าและเริ่มต้น IPC ด้วยFILE*แต่คุณสามารถสร้างFILE*จาก file descriptor ( fdopen()) และในภายหลังการปิดFILEจะเป็นการปิด descriptor ด้วย ดังนั้นคุณสามารถทำ IPC ได้ แต่คุณต้องจัดการกับตัวอธิบายไฟล์เล็กน้อยเพื่ออำนวยความสะดวกให้กับ IPC โดยตรง
คาห์ W

3

FILE *เป็นประโยชน์มากขึ้นเมื่อคุณทำงานกับไฟล์ข้อความและท่านผู้ใช้ / ส่งออกเพราะมันช่วยให้คุณใช้ฟังก์ชัน API เช่นsprintf(), sscanf(), fgets(), feof()ฯลฯ

File descriptor API อยู่ในระดับต่ำดังนั้นจึงอนุญาตให้ทำงานกับซ็อกเก็ตไปป์ไฟล์ที่แมปหน่วยความจำ (และแน่นอนว่าไฟล์ทั่วไป)


1
+1 เนื่องจากคุณเพิ่มไฟล์ที่แมปหน่วยความจำเนื่องจากในการอ่านปัจจุบันของฉันคำตอบอื่น ๆ ได้รับการจัดเตรียมไว้แล้ว
ernie.cordell

3

เพียงแค่ทราบเพื่อจบการอภิปราย (หากสนใจ) ....

fopenอาจไม่ปลอดภัยและคุณควรใช้fopen_sหรือopenตั้งค่าบิตพิเศษ C1X ที่จะนำเสนอxรูปแบบเพื่อให้คุณสามารถfopenด้วยโหมด"rx", "wx"ฯลฯ

ถ้าคุณใช้openคุณอาจพิจารณาหรือopen(..., O_EXCL | O_RDONLY,... )open(..., O_CREAT | O_EXCL | O_WRONLY,... )

ดูตัวอย่างเช่นอย่าทำให้สมมติฐานเกี่ยวกับ fopen () และการสร้างแฟ้ม


ในฐานะที่fopen_sดูเหมือนจะไม่สามารถใช้ได้กับPOSIXผมถือว่า soultion พกพามากที่สุดก็จะไปแล้วopen(2) fdopen(2)(ทิ้งหน้าต่างไว้ข้างๆ) นอกจากนี้อะไรจะเร็วขึ้นfopen_s()หรือopen(2)ตามด้วยfdopen(2)?
Mihir

1

การเรียกระบบส่วนใหญ่ใช้ file descriptor เช่นreadและ write. ฟังก์ชันไลบรารีจะใช้ตัวชี้ไฟล์ ( printf, scanf) แต่ฟังก์ชันของไลบรารีใช้การเรียกระบบภายในเท่านั้น


ฉันไม่แน่ใจว่าทำไมคุณถึงบอกว่าฟังก์ชันไลบรารีใช้เฉพาะการเรียกระบบภายในเท่านั้น: หากคุณหมายถึงฟังก์ชัน CI / O มาตรฐาน (หรืออื่น ๆ สำหรับเรื่องนั้น) ฉันไม่แน่ใจว่าเป็นจริง (สากล?) ไม่อย่างนั้นจะไม่เป็นอย่างที่คุณพูดดังนั้นฉันอยากเห็นภาษาในโพสต์ของคุณสะอาดขึ้นเล็กน้อย ประโยคสุดท้ายทำให้ฉันงงงวย
ernie.cordell

1

ฉันพบแหล่งข้อมูลที่ดีที่นี่โดยให้ภาพรวมระดับสูงของความแตกต่างระหว่างสองสิ่งนี้:

เมื่อคุณต้องการป้อนข้อมูลหรือเอาต์พุตไปยังไฟล์คุณมีทางเลือกของกลไกพื้นฐานสองอย่างสำหรับแสดงการเชื่อมต่อระหว่างโปรแกรมของคุณและไฟล์: file descriptors และ stream ตัวอธิบายไฟล์แสดงเป็นอ็อบเจ็กต์ประเภท int ในขณะที่สตรีมแสดงเป็นอ็อบเจ็กต์ FILE *

File descriptors จัดเตรียมอินเทอร์เฟซระดับต่ำแบบดั้งเดิมสำหรับการดำเนินการอินพุตและเอาต์พุต ทั้งตัวอธิบายไฟล์และสตรีมสามารถแสดงถึงการเชื่อมต่อกับอุปกรณ์ (เช่นเทอร์มินัล) หรือไปป์หรือซ็อกเก็ตสำหรับการสื่อสารกับกระบวนการอื่นเช่นเดียวกับไฟล์ปกติ แต่ถ้าคุณต้องการควบคุมการดำเนินการที่เฉพาะเจาะจงสำหรับอุปกรณ์บางประเภทคุณต้องใช้ตัวอธิบายไฟล์ ไม่มีสิ่งอำนวยความสะดวกในการใช้สตรีมด้วยวิธีนี้ คุณต้องใช้ตัวอธิบายไฟล์ด้วยหากโปรแกรมของคุณจำเป็นต้องทำการอินพุตหรือเอาต์พุตในโหมดพิเศษเช่นอินพุตแบบไม่บล็อก (หรือโพล) (ดูสถานะไฟล์สถานะ)

สตรีมจัดเตรียมอินเทอร์เฟซระดับสูงขึ้นโดยจัดชั้นไว้ด้านบนของสิ่งอำนวยความสะดวกตัวอธิบายไฟล์ดั้งเดิม อินเทอร์เฟซสตรีมถือว่าไฟล์ทุกประเภทเหมือนกันมากยกเว้นเพียงอย่างเดียวคือรูปแบบการบัฟเฟอร์สามรูปแบบที่คุณสามารถเลือกได้ (ดู Stream Buffering)

ข้อได้เปรียบหลักของการใช้อินเทอร์เฟซสตรีมคือชุดของฟังก์ชันสำหรับการดำเนินการอินพุตและเอาต์พุตจริง (ซึ่งตรงข้ามกับการดำเนินการควบคุม) บนสตรีมนั้นสมบูรณ์กว่าและมีประสิทธิภาพมากกว่าสิ่งอำนวยความสะดวกที่เกี่ยวข้องสำหรับตัวอธิบายไฟล์ อินเทอร์เฟซตัวอธิบายไฟล์มีฟังก์ชันง่ายๆสำหรับการถ่ายโอนบล็อกของอักขระเท่านั้น แต่อินเทอร์เฟซสตรีมยังมีฟังก์ชันอินพุตและเอาต์พุตที่มีรูปแบบที่มีประสิทธิภาพ (printf และ scanf) รวมทั้งฟังก์ชันสำหรับอินพุตและเอาต์พุตที่เน้นอักขระและบรรทัด

เนื่องจากสตรีมถูกนำไปใช้ในแง่ของ file descriptor คุณสามารถแยก file descriptor จากสตรีมและดำเนินการระดับต่ำได้โดยตรงบน file descriptor คุณยังสามารถเปิดการเชื่อมต่อเป็นตัวอธิบายไฟล์จากนั้นสร้างสตรีมที่เชื่อมโยงกับตัวอธิบายไฟล์นั้น

โดยทั่วไปคุณควรใช้สตรีมมากกว่าตัวอธิบายไฟล์เว้นแต่จะมีการดำเนินการบางอย่างที่คุณต้องการทำซึ่งสามารถทำได้เฉพาะกับตัวอธิบายไฟล์เท่านั้น หากคุณเป็นโปรแกรมเมอร์เริ่มต้นและไม่แน่ใจว่าจะใช้ฟังก์ชันใดเราขอแนะนำให้คุณมุ่งเน้นไปที่ฟังก์ชันอินพุตที่จัดรูปแบบ (ดูอินพุตที่จัดรูปแบบ) และฟังก์ชันเอาต์พุตที่จัดรูปแบบ (ดูเอาต์พุตที่จัดรูปแบบ)

หากคุณกังวลเกี่ยวกับความสามารถในการพกพาโปรแกรมของคุณไปยังระบบอื่นที่ไม่ใช่ GNU คุณควรทราบด้วยว่าตัวอธิบายไฟล์ไม่สามารถพกพาได้เหมือนกับสตรีม คุณสามารถคาดหวังว่าระบบใด ๆ ที่รัน ISO C เพื่อรองรับสตรีม แต่ระบบที่ไม่ใช่ GNU อาจไม่สนับสนุนตัวอธิบายไฟล์เลยหรืออาจใช้เฉพาะส่วนย่อยของฟังก์ชัน GNU ที่ทำงานกับตัวอธิบายไฟล์ อย่างไรก็ตามฟังก์ชันตัวอธิบายไฟล์ส่วนใหญ่ในไลบรารี GNU C รวมอยู่ในมาตรฐาน POSIX.1

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.