ฉันต้องการที่จะเข้าใจในรายละเอียดความแตกต่างระหว่าง fork () และ vfork () ฉันไม่สามารถแยกแยะหน้าคนได้อย่างสมบูรณ์
ฉันต้องการชี้แจงเพื่อนร่วมงานคนหนึ่งให้ความเห็นว่า " ใน Linux ปัจจุบันไม่มี vfork () แม้ว่าคุณจะเรียกมันว่ามันจะเรียกส้อมภายใน () "
ฉันต้องการที่จะเข้าใจในรายละเอียดความแตกต่างระหว่าง fork () และ vfork () ฉันไม่สามารถแยกแยะหน้าคนได้อย่างสมบูรณ์
ฉันต้องการชี้แจงเพื่อนร่วมงานคนหนึ่งให้ความเห็นว่า " ใน Linux ปัจจุบันไม่มี vfork () แม้ว่าคุณจะเรียกมันว่ามันจะเรียกส้อมภายใน () "
คำตอบ:
หน้าคนมักจะเป็นเอกสารอ้างอิงสั้น ๆ วิกิพีเดียเป็นสถานที่ที่ดีกว่าสำหรับการอธิบายแนวคิด
ทำซ้ำกระบวนการ: สร้างกระบวนการลูกซึ่งเกือบจะเหมือนกับกระบวนการหลัก (ความแตกต่างที่ชัดเจนที่สุดคือกระบวนการใหม่มีรหัสกระบวนการที่แตกต่างกัน) โดยเฉพาะอย่างยิ่ง fork (conceptually) ต้องคัดลอกหน่วยความจำของกระบวนการพาเรนต์ทั้งหมด
เนื่องจากค่อนข้างแพง vfork ถูกคิดค้นเพื่อจัดการกรณีพิเศษทั่วไปที่ไม่จำเป็นต้องทำสำเนา บ่อยครั้งสิ่งแรกที่กระบวนการลูกทำคือการโหลดอิมเมจโปรแกรมใหม่ดังนั้นนี่คือสิ่งที่เกิดขึ้น:
if (fork()) {
# parent process …
} else {
# child process (with a new copy of the process memory)
execve("/bin/sh", …); # discard the process memory
}
การexecve
เรียกจะโหลดโปรแกรมที่เรียกใช้งานได้ใหม่และสิ่งนี้จะแทนที่รหัสของกระบวนการและหน่วยความจำข้อมูลด้วยรหัสของโปรแกรมที่เรียกใช้งานใหม่และหน่วยความจำข้อมูลใหม่ ดังนั้นสำเนาหน่วยความจำทั้งหมดที่สร้างโดยfork
ทั้งหมดเพื่ออะไร
ดังนั้นการvfork
โทรถูกคิดค้น มันไม่ได้ทำสำเนาของหน่วยความจำ ดังนั้นvfork
ราคาถูก แต่มันยากที่จะใช้เนื่องจากคุณต้องแน่ใจว่าคุณไม่ได้เข้าถึงสแต็กหรือพื้นที่ว่างของกระบวนการในกระบวนการลูก โปรดทราบว่าการอ่านอาจเป็นปัญหาได้เนื่องจากกระบวนการหลักยังคงดำเนินการอยู่ ตัวอย่างเช่นรหัสนี้ใช้งานไม่ได้ (อาจหรืออาจไม่ทำงานขึ้นอยู่กับว่าเด็กหรือผู้ปกครองได้รับการแบ่งเวลาก่อน):
if (vfork()) {
# parent process
cmd = NULL; # modify the only copy of cmd
} else {
# child process
execve("/bin/sh", "sh", "-c", cmd, (char*)NULL); # read the only copy of cmd
}
ตั้งแต่การประดิษฐ์ vfork การเพิ่มประสิทธิภาพที่ดีขึ้นได้ถูกประดิษฐ์ขึ้น ระบบที่ทันสมัยส่วนใหญ่รวมถึง Linux ใช้รูปแบบcopy-on-writeโดยที่หน้าในหน่วยความจำกระบวนการจะไม่ถูกคัดลอกในเวลาที่ทำการfork
โทร แต่ต่อมาเมื่อผู้ปกครองหรือลูกเขียนลงในหน้าแรก กล่าวคือแต่ละหน้าเริ่มต้นด้วยการแชร์และยังคงแชร์จนกว่ากระบวนการใดกระบวนการหนึ่งจะเขียนไปยังหน้านั้น กระบวนการที่เขียนได้รับหน้าทางกายภาพใหม่ (ด้วยที่อยู่เสมือนเดียวกัน) การคัดลอกเมื่อเขียนทำให้ vfork ส่วนใหญ่ไม่มีประโยชน์เนื่องจากfork
จะไม่ทำสำเนาใด ๆ ในกรณีที่vfork
สามารถใช้งานได้
Linux เก็บ vfork ไว้ การfork
เรียกระบบจะต้องทำสำเนาของตารางหน่วยความจำเสมือนของกระบวนการแม้ว่าจะไม่ได้คัดลอกหน่วยความจำจริง vfork
ไม่จำเป็นต้องทำเช่นนี้ด้วยซ้ำ การปรับปรุงประสิทธิภาพนั้นไม่มีความสำคัญในแอปพลิเคชันส่วนใหญ่
fork
จำเป็นต้องสร้างการแมปหน่วยความจำเสมือนแยกต่างหากเพื่อให้สำเนาที่คัดลอกเมื่อเขียนมีผลต่อหนึ่งในสองกระบวนการเท่านั้น
fork()
และvfork()
syscalls จะแตกต่างกัน
fork()
syscall สร้างกระบวนการที่สองเหมือนกันกับหน่วยความจำที่แยกต่างหาก vfork()
syscall สร้างกระบวนการที่สองที่ใช้หน่วยความจำเดียวกัน
กับvfork()
ผู้ปกครองจะรอให้ลูกยุติ พาเรนต์สืบทอดมาจากตัวแปรที่โปรแกรมใช้ร่วมกัน ดังนั้นหลังจากที่เด็กถูกเรียกใช้ตัวแปรทั้งหมดที่ถูกแก้ไขภายในเด็กจะยังคงถูกแก้ไขภายในผู้ปกครอง
สำหรับข้อมูลเพิ่มเติมคลิกที่นี่