บัฟเฟอร์จะถูกฟลัชไปที่ดิสก์โดยอัตโนมัติหรือไม่เมื่อกระบวนการออกมา


21

เมื่อฉันเปลี่ยนเส้นทางเอาต์พุตของคำสั่งไปยังไฟล์ (เช่นecho Hello > file) ไฟล์นั้นจะรับประกันว่าจะมีข้อมูลดังกล่าวหลังจากออกคำสั่งหรือไม่ หรือมีหน้าต่างเล็ก ๆ ระหว่างคำสั่งออกและข้อมูลที่เขียนไปยังไฟล์หรือไม่? ฉันต้องการอ่านไฟล์ทันทีหลังจากที่คำสั่งออก แต่ฉันไม่ต้องการอ่านไฟล์เปล่า


1
มันอาจรันคำสั่งทันที แต่ระยะเวลาที่ใช้ในการเปิดไฟล์เขียนและปิดจะขึ้นอยู่กับความเร็วและประเภทของฮาร์ดไดรฟ์ของคุณโปรแกรมที่รันอยู่ ฯลฯ
freginold

ในแง่ของตัวอย่างที่กำหนด 'กระบวนการ' คืออะไร? มีechoและ>ไม่แยก (สั้น) กระบวนการ? และที่echoเหลือของการส่งออกก่อนที่>จะดำเนินการ?
oɔɯǝɹ

1
@ oɔɯǝɹ >คือการเปลี่ยนเส้นทางของเชลล์ มันเหมือนกับว่าโปรแกรมได้เปิดไฟล์ที่มีชื่อสำหรับการเขียนและแทนที่ stdout ด้วยซึ่งเป็นสิ่งที่เชลล์ทำ
Dan D.

7
ฉันคิดว่ามันเป็นความรับผิดชอบของระบบปฏิบัติการที่จะให้คุณfileมีส่วนร่วมHelloโดยไม่คำนึงว่ามันจะถูกล้างออกหรือไม่
Salman

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

คำตอบ:


21

มีบัฟเฟอร์ / แคชหลายชั้นที่เกี่ยวข้อง

  1. แคชของ CPU

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

  2. บัฟเฟอร์ระหว่างดำเนินการ

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

  3. เคอร์เนลบัฟเฟอร์

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

  4. แคชไดรฟ์

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

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


7
เมื่อพิจารณาถึงการแคชของ CPU ดูเหมือนจะไม่เกี่ยวข้องกับฉัน นี่เป็นระดับรายละเอียดที่ไม่จำเป็นที่นี่ จะผ่านรายละเอียดทั้งหมดจนกว่าปริมาณทางกายภาพบางอย่างที่แสดงถึงบิตบนแผ่นดิสก์ฮาร์ดดิสก์หรือหน่วยความจำ ssd จะเปลี่ยนเป็นพลิก
mvw

3
อันที่จริงแคชของ CPU นั้นมีมุมฉากพอสมควร
Simon Richter

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

1
"สิ่งเหล่านี้ส่วนใหญ่ซ่อนอยู่จากโปรแกรมเมอร์แอปพลิเคชัน" ทำไม "ส่วนใหญ่"? ฉันเป็นนักพัฒนาที่ฝังตัวและยกเว้นในระหว่างบูตโหลดเดอร์ (ดังนั้นไม่ใช่ "แอปพลิเคชัน") ฉันไม่สนใจ CPU แคชอย่างสมบูรณ์ ฉันไม่คิดว่าผู้พัฒนาแอพพลิเคชั่นใด ๆ อาจได้รับผลกระทบจากผลกระทบของ CPU cache
Sam

1
@Sam cache ไม่ได้รับความนิยม / ใช้งานร่วมกับการประมวลผลแบบเก็งกำไรอาจถูกใช้ในซีพียูบางตัวเพื่อหลีกเลี่ยงข้อ จำกัด การอ่าน บางทีนี่อาจเป็นสิ่งที่คำตอบอ้างอิงถึง?
John Dvorak

22

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

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

ฉันต้องการอ่านไฟล์ทันทีหลังจากที่คำสั่งออก แต่ฉันไม่ต้องการอ่านไฟล์เปล่า

คุณไม่ควรพบปัญหาในทางปฏิบัติใด ๆ ที่นี่


1
“ หากแอปพลิเคชันไม่มีแคชภายใน” - นั่นเป็นเรื่องใหญ่มาก “ ถ้า”: การใช้งานไลบรารี I / O ส่วนใหญ่ใช้บัฟเฟอร์ stdout ตามค่าเริ่มต้น ที่กล่าวว่ามาตรฐาน C สำหรับอินสแตนซ์สั่งว่าบัฟเฟอร์ stdout จะถูกล้างออกเมื่อออก (แต่อาจไม่ได้ถ้าexitอย่างน้อยก็ไม่ได้เรียกโดยปริยาย) ห้องสมุด / ภาษาอื่น ๆ (เช่น Java!) ให้การรับประกันน้อยลง
Konrad Rudolph

ถ้าหาก จำกัด ไว้เฉพาะการเปลี่ยนเส้นทางดั้งเดิม (เช่นคำสั่งในคำถามของฉัน) มันไม่มีแคชภายในใช่มั้ย
Eric

@Eric ไม่คุณควรจะสบายดี
mtak

10
ฉันไม่แน่ใจว่าฉันได้รับคำตอบนี้หรือไม่ คำถามเกี่ยวกับ "เมื่อกระบวนการจบ" ทุกแอปพลิเคชันที่มีแคชการเขียนภายในจะล้างข้อมูลเหล่านั้นไปยังดิสก์เมื่อออกจากกระบวนการหากไม่ได้เกิดขึ้นก่อนหน้านี้ IOW แคชเหล่านั้นไม่สำคัญที่นี่
MSalters

2
ยิ่งกว่านั้นบัฟเฟอร์ภายในจะถูกล้างออกเมื่อออกหรือหายไปจากที่อยู่ใช่มั้ย ดังนั้นแม้ว่าบัฟเฟอร์ภายในจะไม่ลบออกเนื้อหาจะไม่สามารถสังเกตได้ไม่ว่าจะรอนานแค่ไหนก็ตาม
WorldSEnder

21

บัฟเฟอร์จะถูกฟลัชไปที่ดิสก์โดยอัตโนมัติหรือไม่เมื่อกระบวนการออกมา

โดยทั่วไปคำตอบคือไม่มี

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

แต่ส่วนใหญ่ถ้าไม่ใช่ทั้งหมดไลบรารี I / O มาตรฐานจะบัฟเฟอร์ stdout ตามค่าเริ่มต้น (ในระดับหนึ่ง) และให้การรับประกันที่แตกต่างกันเกี่ยวกับการล้างบัฟเฟอร์อัตโนมัติเมื่อแอปพลิเคชันปิด

C รับประกันว่าทางออกปกติจะล้างบัฟเฟอร์ “ปกติที่ออก” หมายความว่าexitจะเรียกว่า - mainอย่างชัดเจนหรือโดยการกลับมาจาก อย่างไรก็ตามทางออกที่ผิดปกติสามารถหลีกเลี่ยงการโทรนี้ (ดังนั้นจึงทิ้งบัฟเฟอร์ที่ไม่ได้ล้างไว้)

นี่คือตัวอย่างง่ายๆ:

#include <signal.h>
#include <stdio.h>

int main() {
    printf("test");
    raise(SIGABRT);
}

หากคุณรวบรวมและเรียกใช้งานtestจะไม่จำเป็นต้องเขียนลงใน stdout

การเขียนโปรแกรมภาษาอื่น ๆ ให้การค้ำประกันแม้แต่น้อย: Java เช่นไม่ได้อัตโนมัติล้างเมื่อมีการยกเลิกโปรแกรม หากบัฟเฟอร์เอาต์พุตมีบรรทัดที่ไม่ถูกทำลายดังนั้นอาจหายไปเว้นแต่System.out.flush()ถูกเรียกอย่างชัดเจน

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


7
ฉันยังเห็นทางออกที่ผิดปกติเมื่อเครื่องมือบรรทัดคำสั่งกำลังเขียนไปยังไฟล์และไปยัง stdout หรือ stderr เช่นบันทึกการดีบักและผู้ใช้ทำการไพพ์ไปยังส่วนหัวหรือน้อยกว่าจากนั้นพิมพ์ 'q' เพื่อออกน้อยกว่า ไฟล์ดิสก์ไม่ได้ถูกลบทิ้งอย่างสมบูรณ์หากเครื่องมือบรรทัดคำสั่งไม่ได้จัดการ SIGPIPE
Zan Lynx

+1 แต่ "ควรทำทันทีหลังจากคำสั่งยกเลิก" ไม่ถูกต้อง: การเรียกใช้ใด ๆwrite()หรือpwrite()ระบบจะเกิดขึ้นก่อนที่กระบวนการจะออกและนั่นคือเมื่อการเปลี่ยนแปลงไฟล์ปรากฏให้เห็น ดังนั้นการเปลี่ยนแปลงไฟล์ครั้งสุดท้ายแน่นอนก่อนที่กระบวนการจะสิ้นสุดในทันที ฉันคิดว่าถึงแม้จะมีmmap(MAP_SHARED)ไฟล์ แต่ก็ไม่มีวิธีใดที่จะสังเกตว่ากระบวนการยุติเกิดขึ้นก่อนการเปลี่ยนแปลงไฟล์ทั้งหมดที่จะเกิดขึ้น
Peter Cordes

9

ฉันคิดว่ายังไม่มีคำถามตอบปัญหานี้อย่างพอเพียง:

ฉันต้องการอ่านไฟล์ทันทีหลังจากที่คำสั่งออก แต่ฉันไม่ต้องการอ่านไฟล์เปล่า

ในฐานะที่เป็นคำตอบอื่น ๆ อธิบายโปรแกรมดีพฤติกรรมวูบวาบบัฟเฟอร์ไฟล์ภายในก่อนที่กระบวนการยุติตามปกติ หลังจากนั้นข้อมูลอาจยังคงอยู่ในเคอร์เนลหรือบัฟเฟอร์ฮาร์ดแวร์ก่อนที่จะถูกเขียนไปยังที่เก็บข้อมูลถาวร อย่างไรก็ตาม , ความหมายของระบบไฟล์ของการรับประกัน Linux ที่กระบวนการทั้งหมดเห็นเนื้อหาของไฟล์ในลักษณะเดียวกับเคอร์เนลไม่รวมถึงบัฟเฟอร์ภายใน 1

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

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

  • หากกระบวนการเขียนไปยังไฟล์ข้อมูลจะถูกวางไว้ภายในบัฟเฟอร์ในเคอร์เนลสำหรับไฟล์นั้น ในที่สุดเนื้อหาของบัฟเฟอร์จะถูกล้างออกไปยังที่เก็บข้อมูล ในการเข้าถึงการอ่านเวลาเฉลี่ยจะได้รับการตอบสนองจากบัฟเฟอร์เดียวกัน (ดูด้านบน)


1อย่างน้อยสำหรับไฟล์ไดเรกทอรีและลิงก์สัญลักษณ์ทั่วไป FIFOs และซ็อกเก็ตเป็นเรื่องที่แตกต่างเนื่องจากเนื้อหาของพวกเขาจะไม่ถูกจัดเก็บอย่างต่อเนื่อง มีบางกรณีพิเศษของไฟล์ปกติซึ่งเนื้อหาขึ้นอยู่กับว่าใครถาม ตัวอย่างคือไฟล์ใน procfs และ sysfs (คิดว่า/proc/selfเป็นลิงก์สัญลักษณ์ไปยัง ID กระบวนการของกระบวนการที่อ่านลิงก์สัญลักษณ์)


2
พูดอย่างเคร่งครัดมันไม่ใช่ซีแมนทิกส์ระบบไฟล์ของ Linux ที่รับประกันสิ่งนี้มันเป็นความหมาย POSIX ที่ทำ โดยเฉพาะอย่างยิ่ง BSD จะทำงานเหมือนกันเช่นเดียวกับ macOS และแม้แต่ Windows (แม้ว่านี่จะเป็นหนึ่งในไม่กี่กรณีที่ Windows ติดตาม POSIX semantics) สิ่งนี้ยังถือว่าไม่มีใครทำสิ่งแปลก ๆ ด้วยmmap()และ O_DIRECT ซึ่งสามารถนำไปสู่สิ่งต่าง ๆ ที่ไม่ได้อยู่ระหว่างซิงค์กับดิสก์และแคชของหน้าเว็บ
Austin Hemmelgarn

2
@AustinHemmelgarn: พูดอย่างเคร่งครัดว่าเราทั้งคู่ถูกต้องเนื่องจาก Linux ได้รับการออกแบบโดยสนับสนุนแอปพลิเคชัน Unix (System V) ในใจและต่อมาได้สนับสนุน POSIX ซึ่งยังยึดแนวคิดหลายประการเกี่ยวกับ System V.
David Foerster

5

สมมติว่าคำสั่งของคุณถูกเรียกใช้งานโดยบางโปรแกรมโดยใช้ C runtime library ในบางจุดควรเรียกใช้fcloseเพื่อปิดไฟล์ที่เปิดอยู่

man page สำหรับfcloseฟังก์ชัน C บอกว่า:

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

และ man page สำหรับfflushมีโน้ตเหมือนกัน หน้าคนสำหรับcloseพูดว่า:

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

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

หากคุณมีข้อสงสัยให้เขียนบททดสอบ


2
C หรือไม่ทุกอย่างจะ / ควรใช้close()syscall เพื่อปิดตัวให้คำอธิบายของไฟล์
Attie

@Attie: คุณไม่จำเป็นที่จะcloseไฟล์ก่อนที่จะออก (ในโปรแกรม hacky ที่ไม่ได้ตรวจสอบข้อผิดพลาด); เคอร์เนลจะทำความสะอาดโดยเรียกcloseให้คุณอย่างมีประสิทธิภาพหลังจากกระบวนการของคุณตาย คุณจำเป็นต้องfcloseสตรีม stdio ใด ๆ ที่บัฟเฟอร์แล้วหรือปล่อยให้ libc ทำเพื่อคุณด้วยexit(3)ซึ่งตรงข้ามกับการเรียกระบบออกโดยตรง
Peter Cordes

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

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

3

เมื่อฉันเปลี่ยนเส้นทางเอาต์พุตของคำสั่งไปยังไฟล์ (เช่นecho Hello > file) ไฟล์นั้นจะรับประกันว่าจะมีข้อมูลดังกล่าวหลังจากออกคำสั่งหรือไม่

ใช่. เชลล์จะเปิดไฟล์ที่echoส่งออกและส่งออกโดยตรงไปที่ หลังจากคำสั่งจบการทำงาน

หรือมีหน้าต่างเล็ก ๆ ระหว่างคำสั่งออกและข้อมูลที่เขียนไปยังไฟล์หรือไม่?

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

ฉันต้องการอ่านไฟล์ทันทีหลังจากที่คำสั่งออก แต่ฉันไม่ต้องการอ่านไฟล์เปล่า

ไม่ต้องกังวลเคอร์เนลจะเก็บมุมมองหนึ่งของไฟล์เท่านั้นไม่ขึ้นกับว่าเปิดไฟล์บ่อยแค่ไหน


"เคอร์เนลจะเก็บมุมมองหนึ่งของไฟล์": ไม่เป็นความจริงสำหรับmmap(MAP_SHARED): เก็บลงในพื้นที่ mmaped ไม่สอดคล้องกับการอ่านไฟล์ (โดยเธรดหรือกระบวนการอื่น ๆ ) นี่คือเหตุผลที่msync(2)มีอยู่ อย่างน้อยนั่นคือสิ่งที่หน้ามนุษย์เตือน ขึ้นอยู่กับการนำไปใช้จริงลีนุกซ์อาจแมปเพจฟิสิคัลจาก pagecache ซึ่งในกรณีนี้ฉันเดาว่ามันสอดคล้องกัน (การสั่งหน่วยความจำแบบโมดูโล) อย่างไรก็ตามมันยังคงเกิดขึ้นก่อนหน้า_exit(2)นี้ทั้งหมด
Peter Cordes

2

ตามกฎทั่วไปข้อมูลใด ๆ ที่เป็นของเคอร์เนลจะถูกรักษาและล้างข้อมูลโดยเคอร์เนลระยะเวลา write(2)ข้อมูลดังกล่าวรวมถึงข้อมูลที่ถ่ายโอนไปยังหน่วยความจำเคอร์เนลโดยเรียกระบบเช่น

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

นอกจากนี้ฉันไม่เชื่อว่าจะมีการรับประกันระยะเวลาใด ๆสำหรับการล้างข้อมูล - โดยทั่วไปแล้วจะดำเนินการบนพื้นฐานของ "ความพยายามที่สุด" (อ่าน: "เมื่อฉันมีวินาที")


มีการรับประกันว่าการล้างข้อมูลใด ๆ / การลบบัฟเฟอร์จะเกิดขึ้นก่อนที่กระบวนการหลักwaitpid()จะส่งคืนหากการล้างข้อมูลเกิดขึ้นเลย นั่นคือกระบวนการอื่นไม่สามารถสังเกตได้โดยตรงว่ากระบวนการจะสิ้นสุดลงก่อนที่จะทำการแก้ไขไฟล์ที่กระทำโดยกระบวนการนั้น (ฉันบอกว่า "โดยตรง" ที่จะออกกฎการสังเกตทางอ้อมผ่าน NFS timestamps ไฟล์เพราะ NFS แคชไม่ได้เชื่อมโยงกันอย่างสมบูรณ์แบบระหว่างโฮสต์.)
ปีเตอร์ Cordes

@PeterCordes: ฉันคิดว่ามันขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย "ล้าง" เมื่อเทียบกับ "รักษา" สำหรับฉัน "บำรุงรักษา" คือ "ให้มุมมองที่สอดคล้องกัน" (ซึ่งมีการรับประกันที่คุณกล่าวถึง) และ "ล้างข้อมูล" คือ "flush to disk" ซึ่งฉันไม่เชื่อว่ามีการรับประกันเวลา
Mehrdad

โอ้ฉันเข้าใจแล้วว่าคุณกำลังตอบคำถาม "flushed to disk" ของคำถามซึ่งไม่เกี่ยวข้องกับกระบวนการที่จะเห็นในภายหลังเมื่ออ่านไฟล์ "ล้างข้อมูล" ในแง่ของ "ทำให้แคช i / o / หน่วยความจำบัฟเฟอร์สกปรกหมดจด" ไม่มีการรับประกันเวลาเว้นแต่คุณจะใช้fsync/ fdatasyncถึงแม้ว่าบัฟเฟอร์การเขียนกลับบน Linux จะเริ่มหลังจาก/proc/sys/vm/dirty_writeback_centisecsหนึ่งร้อยวินาที (หากไม่ล่าช้าจากการรับส่งข้อมูล I / O อื่น) และการปรับค่าอื่น ๆ ในไดเรกทอรี procfs นั้นก็มีผลเช่นกัน ใหญ่เพื่อให้บัฟเฟอร์เติบโตก่อนที่จะทำการเขียนกลับ)
Peter Cordes

2

หรือมีหน้าต่างเล็ก ๆ ระหว่างคำสั่งออกและข้อมูลที่เขียนไปยังไฟล์หรือไม่?

ไม่ไม่มี

ฉันต้องการอ่านไฟล์ทันทีหลังจากที่คำสั่งออก แต่ฉันไม่ต้องการอ่านไฟล์เปล่า

คุณสามารถอ่านเนื้อหาสุดท้ายของไฟล์ได้ทันทีหลังจากที่คำสั่งออกจากคุณจะไม่อ่านไฟล์เปล่าแทน (ใน C และ C ++ ให้ใช้การเรียกระบบwait , waitpid , wait3หรือwait4เพื่อรอให้โปรแกรมออกจากนั้นอ่านไฟล์เท่านั้นหากคุณใช้เชลล์ภาษาโปรแกรมอื่นหรือไลบรารี (เช่น C library ระบบเรียกหรือคลาสJava Process ) อาจใช้หนึ่งในการเรียกระบบเหล่านี้แล้ว)

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


0

ใช่

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

เมื่อฉันเปลี่ยนเส้นทางเอาต์พุตของคำสั่งไปยังไฟล์ (เช่นไฟล์ echo Hello>) ไฟล์นั้นจะได้รับการรับประกันว่ามีข้อมูลดังกล่าวทันทีหลังจากที่คำสั่งออก

ใช่โดยไม่มีเงื่อนไข การใช้ ">" ที่คุณอธิบายพร้อมด้วย "|" และ "<" เป็นรูปแบบการประมวลผลแบบไปป์ที่โลก Unix และ Linux ใช้เป็นพื้นฐาน คุณจะพบสคริปต์นับร้อยถ้าไม่นับพันทั้งหมดขึ้นอยู่กับพฤติกรรมนี้ในการติดตั้ง Linux ทุกครั้ง

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


นี่คือฟุ่มเฟือยโชคไม่ดี คำตอบเพียงไม่กี่ข้อส่วนใหญ่มุ่งเน้นไปที่ปลาเฮอริ่งแดงของการส่งข้อมูลไปยังที่จัดเก็บข้อมูลที่ไม่ลบเลือน ดูคำตอบของ @ ptsและคำอธิบายอื่น ๆ อีกหลายคำอย่างชัดเจน: การแก้ไขไฟล์เกิดขึ้นก่อนออกหรือไม่ได้เลย
Peter Cordes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.