ไฟล์ถูกเปิดโดยกระบวนการโหลดเข้าสู่ RAM หรือไม่


24

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

กระบวนการสามารถใช้ประโยชน์จากไฟล์อื่น ๆ อ่านหรือเขียนลงไปและถ้าพวกเขาทำไฟล์เหล่านั้นเรียกว่าเปิดไฟล์ มีคำสั่งให้แสดงรายการไฟล์ที่เปิดอยู่ทั้งหมดโดยกระบวนการที่ทำงานอยู่ทั้งหมด: lsof.

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

ข้อสันนิษฐานของฉันคือไฟล์ที่เปิดโดยกระบวนการจะโหลดเข้าสู่ RAM ด้วย ฉันไม่รู้ว่ามันเป็นเรื่องจริงหรือไม่มันเป็นเพียงสัญชาตญาณ

ได้โปรดใครซักคนทำความเข้าใจกับมันได้ไหม?


คำตอบ:


27

อย่างไรก็ตามเมื่อคำสั่งถูกเรียกใช้สำเนาของไฟล์จากฮาร์ดดิสก์จะถูกใส่เข้าไปใน RAM

นี่เป็นสิ่งที่ผิด (โดยทั่วไป) เมื่อโปรแกรมถูกดำเนินการ (ถึงexecve (2) ... ) กระบวนการ (การรันโปรแกรมนั้น) กำลังเปลี่ยนพื้นที่ที่อยู่เสมือนและเคอร์เนลกำลังกำหนดMMU ใหม่เพื่อจุดประสงค์นั้น อ่านยังเกี่ยวกับหน่วยความจำเสมือน ขอให้สังเกตว่าโปรแกรมแอปพลิเคชันสามารถเปลี่ยนพื้นที่ที่อยู่เสมือนโดยใช้mmap (2) & munmap& mprotect (2)นอกจากนี้ยังใช้โดยlinker แบบไดนามิก (ดูld-linux (8) ) ดูเพิ่มเติมmadvise (2)และposix_fadvise (2)และmlock (2)

ข้อบกพร่องของหน้าในอนาคตจะถูกประมวลผลโดยเคอร์เนลเพื่อโหลดหน้า (ขี้เกียจ) จากไฟล์เรียกทำงาน อ่านยังเกี่ยวกับการนวด

เคอร์เนลรักษาขนาดใหญ่แคชหน้า อ่านยังเกี่ยวกับการคัดลอกบนเขียน ดูยังreadahead (2)

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

สำหรับการโทรของระบบเช่นอ่าน (2) & เขียน (2)แคชหน้ายังใช้ หากข้อมูลที่จะอ่านอยู่ในนั้นจะไม่มีดิสก์ IO ที่จะทำ หากจำเป็นต้องใช้ดิสก์ IO ข้อมูลที่อ่านจะเป็นไปได้อย่างมากที่จะใส่ลงในแคชของหน้า ดังนั้นในทางปฏิบัติหากคุณเรียกใช้คำสั่งเดียวกันสองครั้งอาจเกิดขึ้นได้ว่าไม่มีการทำ I / O แบบฟิสิคัลให้กับดิสก์ในครั้งที่สอง (ถ้าคุณมีฮาร์ดดิสก์หมุนเก่า - ไม่ใช่ SSD - คุณอาจได้ยินเช่นนั้น หรือสังเกต LED ฮาร์ดดิสก์ของคุณอย่างระมัดระวัง)

ฉันขอแนะนำให้อ่านหนังสือเช่นระบบปฏิบัติการ: สามชิ้นง่าย ๆ (ดาวน์โหลดได้อย่างอิสระหนึ่งไฟล์ PDF ต่อบท) ซึ่งอธิบายทั้งหมดนี้

ดูเพิ่มเติมLinux Ate My RAMและเรียกใช้คำสั่งเช่นxosview, top, htopหรือcat /proc/self/mapsหรือcat /proc/$$/maps(ดูproc (5) )

PS ฉันมุ่งเน้นไปที่ Linux แต่ระบบปฏิบัติการอื่น ๆ ยังมีหน่วยความจำเสมือนและแคชหน้า


35

ไม่ไฟล์ไม่ได้อ่านในหน่วยความจำโดยอัตโนมัติโดยเปิดขึ้นมา นั่นจะไร้ประสิทธิภาพมาก sedตัวอย่างเช่นอ่านอินพุตบรรทัดต่อบรรทัดเช่นเดียวกับเครื่องมือ Unix อื่น ๆ มันไม่ค่อยจะมีให้มากกว่าเส้นปัจจุบันในหน่วยความจำ

ด้วยawkเหมือนกัน มันอ่านบันทึกในเวลาซึ่งโดยค่าเริ่มต้นคือบรรทัด หากคุณเก็บชิ้นส่วนของข้อมูลเข้าในตัวแปรที่จะเป็นพิเศษของหลักสูตร1

บางคนมีนิสัยชอบทำสิ่งต่าง ๆ เช่น

for line in $(cat file); do ...; done

ตั้งแต่เปลือกจะมีการขยาย$(cat file)แทนคำสั่งอย่างสมบูรณ์ก่อนที่จะใช้แม้กระทั่งการย้ำแรกของforวงนี้จะอ่านทั้งfileในหน่วยความจำ (ในหน่วยความจำที่ใช้โดยเปลือกรันforห่วง) มันค่อนข้างโง่และไม่สุภาพ แต่ควรทำอย่างใดอย่างหนึ่ง

while IFS= read -r line; do ...; done <file

สิ่งนี้จะประมวลผลทีfileละบรรทัด (แต่ต้องอ่านทำความเข้าใจกับ "IFS = read -r line" )

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

ฉันทำงานด้านชีวสารสนเทศศาสตร์และเมื่อประมวลผลข้อมูลจีโนมจำนวนมากฉันจะไม่สามารถทำอะไรได้มากเว้นแต่ฉันจะเก็บบิตของข้อมูลที่จำเป็นอย่างยิ่งในหน่วยความจำเท่านั้น ตัวอย่างเช่นเมื่อฉันต้องการตัดบิตของข้อมูลที่สามารถใช้เพื่อระบุตัวบุคคลจากชุดข้อมูล 1 เทราไบต์ที่มีชุดตัวแปร DNA ในไฟล์ VCF (เนื่องจากข้อมูลประเภทนั้นไม่สามารถเปิดเผยต่อสาธารณะได้) ฉันจะทำทีละบรรทัด การประมวลผลด้วยawkโปรแกรมอย่างง่าย(เป็นไปได้เนื่องจากรูปแบบ VCF เป็นแบบ line-oriented) ฉันไม่อ่านไฟล์ในหน่วยความจำประมวลผลที่นั่นและเขียนมันออกมาอีกครั้ง! หากไฟล์ถูกบีบอัดฉันจะป้อนผ่านzcatหรือgzip -d -cเนื่องจากgzipการประมวลผลข้อมูลจะไม่อ่านไฟล์ทั้งหมดในหน่วยความจำ

แม้ว่าจะมีรูปแบบไฟล์ที่ไม่ได้วางแนวเหมือน JSON หรือ XML แต่ก็มีสตรีมพาร์สเซอร์ที่ทำให้สามารถประมวลผลไฟล์ขนาดใหญ่ได้โดยไม่ต้องเก็บไว้ใน RAM

ด้วยไฟล์ปฏิบัติการมันมีความซับซ้อนเล็กน้อยเนื่องจากไลบรารีที่แบ่งใช้อาจโหลดตามต้องการและ / หรือใช้ร่วมกันระหว่างกระบวนการ (ดูที่การโหลดไลบรารีที่ใช้ร่วมกันและการใช้ RAMตัวอย่างเช่น)

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


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


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

1
@sharkant แน่นอน นั่นเป็นเพียงเรื่องของการเพิ่มข้อมูลลงในตัวแปร (หรืออาร์เรย์หรือแฮชหรือโครงสร้างข้อมูลใด ๆ ที่เป็นภาษาของคำถาม) จนกว่าไฟล์ทั้งหมดจะถูกเก็บไว้ ด้วยawk, จะเพิ่มทุกบรรทัดของไฟล์ป้อนข้อมูลไปยังอาร์เรย์{ a[i++] = $0 } aคุณอาจต้องการค้นหาฟังก์ชั่น C mmap()แต่การใช้งานอาจเป็นเรื่องเล็กน้อยที่นี่
Kusalananda

6
sed, awkและโปรแกรมเชิงเส้นอื่น ๆ ไม่อ่านบรรทัดในหน่วยความจำทีละครั้งเนื่องจากไฟล์ข้อความธรรมดาไม่มีดัชนีบรรทัดและ API ของระบบไฟล์และฮาร์ดแวร์ระบบจัดเก็บข้อมูลระดับต่ำอ่าน "เซกเตอร์" หนึ่งรายการหรือมากกว่า หรือ 1024 ไบต์) ในแต่ละครั้ง ฉันจะแปลกใจถ้าระบบปฏิบัติการอ่านน้อยกว่า 8KB ในหน่วยความจำก่อนประมวลผลบรรทัดแรก
รัสเซล Borogove

5
แม้ว่ายูทิลิตี้อย่างเช่นsedจะอ่านเพียงหนึ่งบรรทัดต่อครั้งในหน่วยความจำ แต่มันก็คุ้มค่าที่จะกล่าวถึงว่าระบบปฏิบัติการจะใช้ RAM อิสระในการแคชไฟล์เพื่อให้สามารถเข้าถึงได้อย่างรวดเร็ว หากคุณกำลังเรียกใช้sedไฟล์ขนาดเล็กมันเป็นไปได้ที่ระบบปฏิบัติการจะแคชไฟล์ทั้งหมดในหน่วยความจำและการดำเนินการทั้งหมดจะทำใน RAM ดู: en.wikipedia.org/wiki/Page_cache
Sean Dawson

5
@sharkant มีการใช้ในการเข้าถึงไฟล์ทั้งหมดในหน่วยความจำ (ดูคำตอบอื่น ๆ mmap คือการเรียกระบบคำหลักที่นี่) ตัวอย่างเช่นระบบฐานข้อมูลมักจะต้องการเพื่อความสะดวกและความเร็วในการเข้าถึงฐานข้อมูลทั้งหมดหรืออย่างน้อยดัชนีบางส่วนที่แมปไว้ในหน่วยความจำ นี่ไม่ได้แปลว่าทั้งหมดนั้นอยู่ในความทรงจำจริง ๆ ระบบปฏิบัติการมีอิสระที่จะ "เสแสร้ง" ว่าไฟล์นั้นอยู่ในหน่วยความจำ มันบอกแอปพลิเคชัน "ที่นี่ในช่วงหน่วยความจำนี้คือไฟล์ของคุณ" และเมื่อมีการอ่านเสร็จแล้ว (เช่นเดียวกับเมื่อกระบวนการถูกเปลี่ยนออก) ข้อมูลจะถูกอ่านจริง
Jonas Schäfer

5

ไม่ในขณะที่การมี RAM กิ๊กวันนี้ยอดเยี่ยมมีช่วงเวลาที่ RAM เป็นทรัพยากรที่ จำกัด มาก (ฉันได้เรียนรู้การเขียนโปรแกรมบน VAX 11/750 พร้อม RAM 2MB) และสิ่งเดียวใน RAM คือปฏิบัติการและหน้าข้อมูล ของกระบวนการที่ใช้งานอยู่และข้อมูลไฟล์ที่อยู่ในแคชบัฟเฟอร์
แคชบัฟเฟอร์ถูกล้างข้อมูลและหน้าข้อมูลถูกสลับออก และบ่อยครั้งในบางครั้ง เพจที่ปฏิบัติการได้แบบอ่านอย่างเดียวถูกเขียนทับและตารางเพจถูกทำเครื่องหมายดังนั้นหากโปรแกรมแตะหน้าเหล่านั้นอีกครั้งเพจนั้นจะถูกทำเพจจากระบบไฟล์ ข้อมูลถูกเพจเอาต์จากการสลับ ดังที่ระบุไว้ข้างต้นไลบรารี STDIO ดึงข้อมูลในบล็อกและได้รับโดยโปรแกรมตามต้องการ: fgetc, fgets, fread ฯลฯ ด้วย mmap ไฟล์สามารถถูกแม็พเข้ากับพื้นที่แอดเดรสของกระบวนการเช่นทำด้วย ไลบรารีวัตถุที่ใช้ร่วมกันหรือแม้กระทั่งไฟล์ปกติ ใช่คุณอาจมีระดับการควบคุมถ้าอยู่ใน RAM หรือไม่ (mlock) แต่มันไปไกล (ดูที่ส่วนรหัสข้อผิดพลาดของ mlock)


1
คำสั่ง "RAM ของคุณจะเล็กเกินไปสำหรับไฟล์ของคุณ" เป็นจริงในขณะนี้เหมือนในสมัยก่อนของ VAX
Federico Poloni

1
@Federico_Poloni วันนี้ไม่เป็นความจริงเลย ที่นายจ้างคนสุดท้ายของฉันเรามีพีซีเวิร์คสเตชั่นที่มี RAM 1Tb และฮาร์ดดิสก์เพียง 0.5Tb (คลาสปัญหา: อินพุตขนาดเล็กเอาต์พุตขนาดกลางอาร์เรย์ที่เข้าถึงแบบสุ่มขนาดใหญ่ระหว่างการคำนวณ)
nigel222
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.