การเปิดไฟล์ทำหน้าที่อะไร


266

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

แต่สิ่งที่เปิดดำเนินการจริงทำอะไร?

หน้าคู่มือสำหรับฟังก์ชั่นทั่วไปอย่าบอกอะไรเลยนอกจาก 'เปิดไฟล์สำหรับอ่าน / เขียน':

http://www.cplusplus.com/reference/cstdio/fopen/

https://docs.python.org/3/library/functions.html#open

เห็นได้ชัดว่าผ่านการใช้งานฟังก์ชั่นที่คุณสามารถบอกได้ว่ามันเกี่ยวข้องกับการสร้างวัตถุบางชนิดที่เอื้อต่อการเข้าถึงไฟล์

อีกวิธีหนึ่งในการวางสิ่งนี้คือถ้าฉันจะใช้openฟังก์ชั่นมันต้องทำอะไรบน Linux?


13
การแก้ไขคำถามนี้เพื่อมุ่งเน้นCและ Linux; ตั้งแต่สิ่งที่ Linux และ Windows แตกต่าง มิฉะนั้นมันจะกว้างเกินไป นอกจากนี้ภาษาระดับสูงกว่าจะจบลงด้วยการเรียก C API สำหรับระบบหรือการคอมไพล์ลงไปที่ C เพื่อดำเนินการดังนั้นการออกจากระดับ "C" จะถูกวางไว้ที่ Least Common Denominator
George Stocker

1
ไม่พูดถึงว่าไม่ทุกภาษาโปรแกรมที่มีสถานที่นี้หรือจะเป็นสถานที่ที่มีความสูงขึ้นอยู่กับสภาพแวดล้อม แน่นอนว่าเป็นไปได้ยากในทุกวันนี้ แต่จนถึงทุกวันนี้การจัดการไฟล์เป็นทางเลือกที่สมบูรณ์ของ ANSI Forth และไม่เคยมีมาก่อนในการใช้งานบางอย่างในอดีต

คำตอบ:


184

ในเกือบทุกภาษาระดับสูงฟังก์ชั่นที่เปิดไฟล์นั้นเป็นตัวหุ้มรอบการเรียกระบบเคอร์เนลที่เกี่ยวข้อง มันอาจทำสิ่งแฟนซีอื่น ๆ เช่นกัน แต่ในระบบปฏิบัติการร่วมสมัยการเปิดไฟล์จะต้องผ่านเคอร์เนลเสมอ

นี่คือเหตุผลที่อาร์กิวเมนต์ของfopenฟังก์ชันไลบรารีหรือ Python openมีลักษณะคล้ายกับข้อโต้แย้งของการopen(2)เรียกระบบ

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

ฉันไม่ได้สนใจที่จะใช้ฟังก์ชั่นของตัวเอง เพียงแค่ทำความเข้าใจว่าสิ่งที่เกิดขึ้น ... 'เกินกว่าภาษา' หากคุณต้องการ

ในระบบปฏิบัติการที่คล้าย Unix การเรียกสำเร็จเพื่อopenส่งคืน "file descriptor" ซึ่งเป็นเพียงจำนวนเต็มในบริบทของกระบวนการผู้ใช้ descriptor นี้จะถูกส่งผ่านไปยังการเรียกใด ๆ ที่โต้ตอบกับไฟล์ที่เปิดและหลังจากการโทรcloseมัน descriptor จะไม่ถูกต้อง

เป็นสิ่งสำคัญที่จะต้องทราบว่าการเรียกร้องให้openทำหน้าที่เหมือนจุดตรวจสอบความถูกต้องของการตรวจสอบต่างๆ ถ้าไม่ได้ทุกเงื่อนไขที่จะได้พบกับการเรียกล้มเหลวโดยกลับแทนการอธิบายและชนิดของข้อผิดพลาดที่ระบุไว้ใน-1 errnoการตรวจสอบที่สำคัญคือ:

  • ไม่ว่าจะเป็นไฟล์ที่มีอยู่;
  • ระบุว่ากระบวนการเรียกนั้นมีสิทธิพิเศษในการเปิดไฟล์นี้ในโหมดที่ระบุหรือไม่ สิ่งนี้ถูกกำหนดโดยการจับคู่การอนุญาตไฟล์ ID เจ้าของและ ID กลุ่มกับ ID ที่เกี่ยวข้องของกระบวนการเรียก

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


2
เป็นที่น่าสังเกตว่าใน OSE ที่มีลักษณะคล้าย Unix ตัวอธิบายไฟล์โครงสร้างเคอร์เนลจะถูกแมปกับเรียกว่า "open file description" ดังนั้นกระบวนการ FD จะถูกแมปกับเคอร์เนล OFD นี่เป็นสิ่งสำคัญที่จะต้องเข้าใจเอกสารประกอบ ตัวอย่างเช่นดูman dup2และตรวจสอบความละเอียดระหว่างตัวอธิบายไฟล์ที่เปิด (นั่นคือ FD ที่เกิดขึ้นที่จะเปิด) และคำอธิบายไฟล์ที่เปิด (OFD)
rodrigo

1
ใช่สิทธิ์จะถูกตรวจสอบในเวลาเปิด คุณสามารถไปและอ่านซอร์สสำหรับการใช้งาน "open" ของเคอร์เนล: lxr.free-electrons.com/source/fs/open.cแม้ว่าจะมอบหมายงานส่วนใหญ่ให้กับไดรเวอร์ระบบไฟล์ที่เฉพาะเจาะจง
pjc50

1
(ในระบบ ext2 สิ่งนี้จะเกี่ยวข้องกับการอ่านรายการไดเรกทอรีเพื่อระบุว่า inode ใดมีข้อมูลเมตาในจากนั้นโหลด inode นั้นลงในแคช inode โปรดทราบว่าอาจมีระบบ pseudofiles เช่น "/ proc" และ "/ sys" ซึ่งอาจทำสิ่งใดก็ได้ เมื่อคุณเปิดไฟล์)
pjc50

1
โปรดทราบว่าการตรวจสอบไฟล์เปิด - ว่าไฟล์มีอยู่ว่าคุณได้รับอนุญาต - ในทางปฏิบัติไม่เพียงพอ ไฟล์อาจหายไปหรือการอนุญาตสามารถเปลี่ยนแปลงได้ภายใต้การควบคุมของคุณ ระบบไฟล์บางระบบพยายามป้องกันสิ่งนี้ แต่ตราบใดที่ระบบปฏิบัติการของคุณรองรับการจัดเก็บข้อมูลเครือข่ายมันเป็นไปไม่ได้ที่จะป้องกัน (ระบบปฏิบัติการสามารถ "ตื่นตระหนก" ได้หากระบบไฟล์ในเครื่องทำงานผิดปกติและสมเหตุสมผล: ระบบที่ทำเช่นนั้น ระบบปฏิบัติการที่ใช้งานได้) การตรวจสอบเหล่านี้จะยังทำที่เปิดแฟ้ม แต่ต้อง (อย่างมีประสิทธิภาพ) ทำได้ที่ทุกคนสามารถเข้าถึงไฟล์อื่น ๆ เช่นกัน
Yakk - Adam Nevraumont

2
อย่าลืมการประเมินและ / หรือการสร้างล็อค สิ่งเหล่านี้สามารถแชร์หรือเอกสิทธิ์และสามารถส่งผลกระทบต่อไฟล์ทั้งหมดหรือบางส่วนเท่านั้น
Thinkeye

83

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

0  int sys_open(const char *filename, int flags, int mode) {
1      char *tmp = getname(filename);
2      int fd = get_unused_fd();
3      struct file *f = filp_open(tmp, flags, mode);
4      fd_install(fd, f);
5      putname(tmp);
6      return fd;
7  }

สั้น ๆ นี่คือสิ่งที่รหัสทำตามบรรทัด:

  1. จัดสรรบล็อกของหน่วยความจำที่ควบคุมโดยเคอร์เนลและคัดลอกชื่อไฟล์จากหน่วยความจำที่ผู้ใช้ควบคุม
  2. เลือกไฟล์ descriptor ที่ไม่ได้ใช้ซึ่งคุณสามารถคิดว่าเป็นดัชนีจำนวนเต็มเป็นรายการไฟล์ที่เปิดอยู่ในปัจจุบัน แต่ละกระบวนการมีรายการของตัวเองแม้ว่ามันจะดูแลโดยเคอร์เนล รหัสของคุณไม่สามารถเข้าถึงได้โดยตรง รายการในรายการมีข้อมูลใด ๆ ที่ระบบไฟล์พื้นฐานจะใช้เพื่อดึงไบต์ออกจากดิสก์เช่นหมายเลข inode, สิทธิ์กระบวนการ, เปิดสถานะและอื่น ๆ
  3. filp_openฟังก์ชั่นที่มีการดำเนินการ

    struct file *filp_open(const char *filename, int flags, int mode) {
            struct nameidata nd;
            open_namei(filename, flags, mode, &nd);
            return dentry_open(nd.dentry, nd.mnt, flags);
    }
    

    ซึ่งทำสองสิ่ง:

    1. ใช้ระบบไฟล์เพื่อค้นหา inode (หรือโดยทั่วไปตัวเรียงลำดับใด ๆ ของระบบไฟล์ที่ใช้) ที่สอดคล้องกับชื่อไฟล์หรือพา ธ ที่ส่งผ่าน
    2. สร้าง a struct fileด้วยข้อมูลที่จำเป็นเกี่ยวกับ inode และส่งคืน struct นี้จะกลายเป็นรายการในรายการของไฟล์ที่เปิดที่ฉันกล่าวถึงก่อนหน้านี้
  4. จัดเก็บ ("ติดตั้ง") โครงสร้างที่ส่งคืนลงในรายการไฟล์ที่เปิดของกระบวนการ

  5. เพิ่มการจัดสรรบล็อกของหน่วยความจำที่ควบคุมโดยเคอร์เนล
  6. กลับอธิบายไฟล์ซึ่งจากนั้นจะสามารถส่งผ่านไปยังฟังก์ชั่นการดำเนินงานไฟล์เช่นread(), และwrite() close()แต่ละเหล่านี้จะส่งมอบการควบคุมเคอร์เนลซึ่งสามารถใช้ file descriptor เพื่อค้นหาตัวชี้ไฟล์ที่เกี่ยวข้องในรายการของกระบวนการและใช้ข้อมูลในตัวชี้ไฟล์นั้นเพื่อทำการอ่านเขียนหรือปิด

ถ้าคุณรู้สึกมีความทะเยอทะยานคุณสามารถเปรียบเทียบเช่นนี้ง่ายที่จะดำเนินการตามopen()สายระบบในลินุกซ์เคอร์เนล, do_sys_open()ฟังก์ชั่นที่เรียกว่า คุณไม่ควรมีปัญหาในการค้นหาความคล้ายคลึงกัน


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

  • open_namei()และdentry_open()เรียกใช้รหัสระบบไฟล์ซึ่งเป็นส่วนหนึ่งของเคอร์เนลเพื่อเข้าถึงข้อมูลเมตาและเนื้อหาสำหรับไฟล์และไดเรกทอรี ระบบแฟ้มอ่านไบต์ดิบจากดิสก์และตีความรูปแบบไบต์เหล่านั้นเป็นต้นไม้ของไฟล์และไดเรกทอรี
  • ระบบไฟล์ใช้เลเยอร์อุปกรณ์บล็อกซึ่งเป็นส่วนหนึ่งของเคอร์เนลอีกครั้งเพื่อรับไบต์ดิบเหล่านั้นจากไดรฟ์ (ข้อเท็จจริงที่สนุก: Linux ช่วยให้คุณเข้าถึงข้อมูลดิบจากเลเยอร์อุปกรณ์บล็อกโดยใช้/dev/sdaและไม่ชอบ)
  • เลเยอร์อุปกรณ์บล็อกเรียกใช้ไดรเวอร์อุปกรณ์จัดเก็บข้อมูลซึ่งเป็นรหัสเคอร์เนลเพื่อแปลจากคำสั่งระดับกลางเช่น "read เซกเตอร์ X" ไปยังคำสั่งอินพุต / เอาต์พุตแต่ละรายการในรหัสเครื่อง มีไดรเวอร์อุปกรณ์เก็บข้อมูลหลายประเภทรวมถึงIDE , (S) ATA , SCSI , Firewireและอื่น ๆ ซึ่งสอดคล้องกับมาตรฐานการสื่อสารที่แตกต่างกันซึ่งไดรฟ์สามารถใช้งานได้ (โปรดทราบว่าการตั้งชื่อไม่เป็นระเบียบ)
  • คำแนะนำ I / O ใช้ความสามารถในตัวของชิปโปรเซสเซอร์และคอนโทรลเลอร์ของเมนบอร์ดเพื่อส่งและรับสัญญาณไฟฟ้าบนลวดที่ไปยังไดรฟ์ทางกายภาพ นี่คือฮาร์ดแวร์ไม่ใช่ซอฟต์แวร์
  • ที่ปลายอีกด้านหนึ่งเฟิร์มแวร์ของดิสก์ (รหัสควบคุมฝังตัว) ตีความสัญญาณไฟฟ้าเพื่อหมุนจานและย้ายหัว (HDD) หรืออ่านเซลล์แฟลช ROM (SSD) หรืออะไรก็ตามที่จำเป็นในการเข้าถึงข้อมูลบน อุปกรณ์เก็บข้อมูลชนิดนั้น

นอกจากนี้ยังอาจจะเนื่องจากค่อนข้างไม่ถูกต้องแคช :-P อย่างจริงจังแม้ว่าจะมีรายละเอียดมากมายที่ฉันทิ้งไว้ - บุคคล (ไม่ใช่ฉัน) สามารถเขียนหนังสือหลายเล่มที่อธิบายว่ากระบวนการทั้งหมดนี้ทำงานอย่างไร แต่นั่นควรให้ความคิดแก่คุณ


67

ระบบไฟล์หรือระบบปฏิบัติการใด ๆ ที่คุณต้องการพูดคุยก็ดีด้วย ดี!


บน ZX Spectrum การกำหนดค่าเริ่มต้นให้LOADคำสั่งจะทำให้ระบบเข้าสู่ลูปที่แน่นอ่านค่า Audio In line

จุดเริ่มต้นของข้อมูลถูกระบุด้วยโทนเสียงคงที่และหลังจากนั้นตามลำดับของพัลส์ยาว / สั้นตามมาโดยที่พัลส์สั้นสำหรับไบนารี0และอีกอันหนึ่งสำหรับไบนารี1( https://en.wikipedia.org/ wiki / ZX_Spectrum_software ) วงโหลดที่แน่นจะรวบรวมบิตจนกว่าจะเติมไบต์ (8 บิต) เก็บสิ่งนี้ไว้ในหน่วยความจำเพิ่มตัวชี้หน่วยความจำจากนั้นวนกลับเพื่อสแกนหาบิตเพิ่มเติม

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

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


พื้นหลังเล็กน้อยในคำตอบนี้

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

"tight loop" ถูกกล่าวถึงเนื่องจาก (1) CPU, Z80-A (ถ้าใช้หน่วยความจำ), ช้ามาก: 3.5 MHz และ (2) Spectrum ไม่มีนาฬิกาภายใน! นั่นหมายความว่ามันจะต้องรักษานับT-state (เวลาการสอน) ให้ถูกต้องทุกครั้ง เดียว คำแนะนำ. ภายในวงนั้นเพียงเพื่อรักษาจังหวะบี๊ปที่ถูกต้อง
โชคดีที่ความเร็วของ CPU ต่ำมีข้อได้เปรียบที่แตกต่างกันซึ่งคุณสามารถคำนวณจำนวนรอบบนกระดาษหนึ่งแผ่นและเวลาโลกแห่งความจริงที่พวกเขาจะทำ


10
@BillWoodger: ใช่ แต่มันเป็นคำถามที่ยุติธรรม (ฉันหมายถึงคุณ) ฉันลงคะแนนให้ใกล้ว่า "กว้างเกินไป" และคำตอบของฉันมีไว้เพื่อแสดงให้เห็นว่าคำถามนั้นกว้างมากจริง ๆ
usr2564301

8
ฉันคิดว่าคุณได้คำตอบที่มากเกินไป ZX Spectrum มีคำสั่ง OPEN และนั่นแตกต่างจาก LOAD โดยสิ้นเชิง และยากที่จะเข้าใจ
rodrigo

3
ฉันไม่เห็นด้วยกับการปิดคำถาม แต่ฉันชอบคำตอบของคุณ
Enzo Ferber

23
แม้ว่าฉันจะแก้ไขคำถามของฉันเพื่อ จำกัด การ linux / windows OS ในความพยายามที่จะให้เปิด แต่คำตอบนี้ถูกต้องและมีประโยชน์ทั้งหมด ตามที่ระบุไว้ในคำถามของฉันฉันไม่ต้องการใช้อะไรหรือเพื่อให้คนอื่นทำงานของฉันฉันต้องการเรียนรู้ หากต้องการเรียนรู้คุณต้องถามคำถาม 'ใหญ่' หากเราปิดคำถามอย่างต่อเนื่องเกี่ยวกับ SO ที่ 'กว้างเกินไป' ความเสี่ยงที่จะกลายเป็นสถานที่สำหรับให้คนเขียนรหัสของคุณโดยไม่ต้องอธิบายอะไรอะไรที่ไหนหรือทำไม ฉันอยากจะเก็บมันไว้เป็นที่ ๆ ฉันสามารถเรียนรู้ได้
jramm

14
คำตอบนี้ดูเหมือนจะพิสูจน์ว่าการตีความคำถามของคุณกว้างเกินไปแทนที่จะเป็นคำถามที่กว้างเกินไป
jwg

17

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

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


6
สิ่งนี้เกี่ยวข้องกับคำถามจริงหรือไม่
Bill Woodger

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

1
ดังนั้นอีกครั้งไม่ตรวจสอบสิทธิ์?
Bill Woodger

11

การทำบัญชีส่วนใหญ่ ซึ่งรวมถึงการตรวจสอบต่าง ๆ เช่น "มีไฟล์อยู่หรือไม่" และ "ฉันมีสิทธิ์ในการเปิดไฟล์นี้สำหรับการเขียนหรือไม่"

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

ส่วนที่สำคัญที่สุดในระดับรหัสคือมันช่วยให้คุณจัดการกับไฟล์ที่เปิดซึ่งคุณใช้สำหรับการดำเนินการอื่น ๆ ทั้งหมดที่คุณทำกับไฟล์ คุณไม่สามารถใช้ชื่อไฟล์แทนหมายเลขอ้างอิงนี้ได้หรือไม่? แน่นอน - แต่การใช้ที่จับช่วยให้คุณได้เปรียบ:

  • ระบบสามารถติดตามไฟล์ทั้งหมดที่เปิดอยู่ในปัจจุบันและป้องกันไม่ให้ถูกลบ (ตัวอย่าง)
  • ระบบปฏิบัติการที่ทันสมัยนั้นถูกสร้างขึ้นโดยใช้มือจับ - มีสิ่งที่มีประโยชน์มากมายที่คุณสามารถทำได้ด้วยมือจับและมือจับประเภทต่างๆนั้นมีพฤติกรรมเกือบเหมือนกัน ตัวอย่างเช่นเมื่อการดำเนินการแบบอะซิงโครนัส I / O เสร็จสิ้นบนหมายเลขอ้างอิงไฟล์ Windows หมายเลขอ้างอิงจะถูกส่งสัญญาณ - สิ่งนี้ช่วยให้คุณสามารถบล็อกที่จับได้จนกว่าจะมีการส่งสัญญาณหรือเพื่อดำเนินการแบบอะซิงโครนัสทั้งหมด การรอที่จุดจับไฟล์จะเหมือนกับการรอที่จุดจับด้าย (ส่งสัญญาณเช่นเมื่อปลายสายสิ้นสุดลง) จุดจับกระบวนการ (อีกครั้งส่งสัญญาณเมื่อกระบวนการสิ้นสุด) หรือซ็อกเก็ต (เมื่อการดำเนินการแบบอะซิงโครนัสเสร็จสิ้น) ที่สำคัญก็คือมือจับนั้นเป็นเจ้าของโดยกระบวนการที่เกี่ยวข้องดังนั้นเมื่อกระบวนการถูกยกเลิกโดยไม่คาดคิด (หรือแอปพลิเคชันเขียนได้ไม่ดี) ระบบปฏิบัติการจะรู้ว่าตัวจัดการนั้นสามารถปล่อยอะไรได้บ้าง
  • การดำเนินการส่วนใหญ่เป็นตำแหน่ง - คุณreadมาจากตำแหน่งสุดท้ายในไฟล์ของคุณ ด้วยการใช้จุดจับเพื่อระบุ "การเปิด" ของไฟล์คุณสามารถมีจุดจับพร้อมกันหลายตัวในไฟล์เดียวกันโดยแต่ละตัวอ่านจากตำแหน่งของตัวเอง ในทางที่จับทำหน้าที่เป็นหน้าต่างที่เคลื่อนย้ายได้ลงในไฟล์ (และวิธีที่จะออกคำขอ I / O แบบอะซิงโครนัสซึ่งมีประโยชน์มาก)
  • จับเป็นมากมีขนาดเล็กกว่าชื่อไฟล์ หมายเลขอ้างอิงมักจะมีขนาดของตัวชี้โดยทั่วไป 4 หรือ 8 ไบต์ ในทางกลับกันชื่อไฟล์อาจมีหลายร้อยไบต์
  • ที่จับช่วยให้ระบบปฏิบัติการย้ายไฟล์ได้แม้ว่าแอปพลิเคชั่นจะเปิดอยู่ก็ตามหมายเลขอ้างอิงยังคงใช้ได้และยังคงชี้ไปที่ไฟล์เดียวกันแม้ว่าชื่อไฟล์จะเปลี่ยนไปก็ตาม

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


7

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

มันอยู่ในคำสั่งเหล่านั้นที่การอ่านจริงจะได้รับการจัดส่ง

ระบบปฏิบัติการมักจะเริ่มต้นการอ่านโดยเริ่มการอ่านเพื่อเติมบัฟเฟอร์ที่เกี่ยวข้องกับที่จับ จากนั้นเมื่อคุณทำการอ่านจริงมันสามารถส่งคืนเนื้อหาของบัฟเฟอร์ได้ทันทีแทนที่จะต้องรอบนดิสก์ IO

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


5

โดยทั่วไปการเรียกเพื่อเปิดจำเป็นต้องค้นหาไฟล์จากนั้นทำการบันทึกสิ่งที่จำเป็นเพื่อให้การดำเนินการ I / O ในภายหลังสามารถค้นหาได้อีกครั้ง ค่อนข้างคลุมเครือ แต่มันจะเป็นจริงในทุกระบบปฏิบัติการที่ฉันสามารถนึกได้ทันที ข้อมูลเฉพาะแตกต่างกันไปในแต่ละแพลตฟอร์ม มีคำตอบอยู่แล้วที่นี่พูดถึงระบบปฏิบัติการเดสก์ท็อปยุคปัจจุบัน ฉันได้เขียนโปรแกรมเล็ก ๆ น้อย ๆ เกี่ยวกับ CP / M ดังนั้นฉันจะให้ความรู้เกี่ยวกับวิธีการทำงานกับ CP / M (MS-DOS อาจทำงานในลักษณะเดียวกัน แต่เพื่อความปลอดภัยมันไม่ได้ทำแบบนี้ในวันนี้ตามปกติ )

ใน CP / M คุณมีสิ่งที่เรียกว่า FCB (ตามที่คุณกล่าวถึง C คุณสามารถเรียกมันว่า struct มันเป็นพื้นที่ต่อเนื่อง 35- ไบต์ใน RAM ที่มีเขตข้อมูลต่าง ๆ ) FCB มีฟิลด์สำหรับเขียนชื่อไฟล์และจำนวนเต็ม (4 บิต) เพื่อระบุดิสก์ไดรฟ์ จากนั้นเมื่อคุณเรียกใช้ Open File ของเคอร์เนลคุณจะส่งตัวชี้ไปที่ struct นี้โดยวางลงในหนึ่งในการลงทะเบียนของ CPU หลังจากนั้นไม่นานระบบปฏิบัติการจะกลับมาพร้อมโครงสร้างที่เปลี่ยนแปลงเล็กน้อย สิ่งที่ I / O ที่คุณทำกับไฟล์นี้คุณส่งตัวชี้ไปที่ struct นี้เพื่อการเรียกของระบบ

CP / M ทำอะไรกับ FCB นี้ มันสงวนเขตข้อมูลบางอย่างสำหรับการใช้งานของตัวเองและใช้สิ่งเหล่านี้เพื่อติดตามไฟล์ดังนั้นคุณจะไม่เคยสัมผัสมันจากภายในโปรแกรมของคุณ การดำเนินการ Open File จะค้นหาในตารางที่จุดเริ่มต้นของดิสก์เพื่อค้นหาไฟล์ที่มีชื่อเดียวกับสิ่งที่อยู่ใน FCB (อักขระตัวแทน '?' ตรงกับอักขระใด ๆ ) หากพบไฟล์มันจะคัดลอกข้อมูลบางอย่างลงใน FCB รวมถึงตำแหน่งทางกายภาพของไฟล์บนดิสก์ดังนั้นการโทร I / O ที่ตามมาจะเรียก BIOS ในที่สุดซึ่งอาจส่งผ่านตำแหน่งเหล่านี้ไปยังไดรเวอร์ดิสก์ ในระดับนี้เฉพาะเจาะจงแตกต่างกันไป


-7

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

คำสั่งเปิดจะสร้างการเรียกของระบบซึ่งจะคัดลอกเนื้อหาของไฟล์จากหน่วยเก็บข้อมูลรอง (ฮาร์ดดิสก์) ไปยังหน่วยเก็บข้อมูลหลัก (Ram)

และเรา 'ปิด' ไฟล์เนื่องจากเนื้อหาที่แก้ไขของไฟล์จะต้องสะท้อนให้เห็นถึงไฟล์ต้นฉบับที่อยู่ในฮาร์ดดิสก์ :)

หวังว่าจะช่วย

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