เธรดถูกคัดลอกเมื่อเรียก fork หรือไม่?


31

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

คำตอบ:


29

เลขที่

fork()กระทู้จะไม่คัดลอกบน POSIX ระบุว่า (เน้นเป็นของฉัน):

ทางแยก - สร้างกระบวนการใหม่

กระบวนการจะถูกสร้างขึ้นด้วยหัวข้อเดียว หากกระบวนการแบบมัลติเธรดเรียก fork () กระบวนการใหม่จะต้องมีเรพลิกาของเธรดการโทรและพื้นที่แอดเดรสทั้งหมดซึ่งอาจรวมถึงสถานะของ mutexes และทรัพยากรอื่น ๆ ดังนั้นเพื่อหลีกเลี่ยงข้อผิดพลาดกระบวนการลูกอาจดำเนินการการดำเนินการแบบ async-signal-safe จนกว่าจะถึงเวลาที่เรียกใช้ฟังก์ชัน exec อย่างใดอย่างหนึ่ง

เพื่อหลีกเลี่ยงปัญหานี้จึงมีpthread_atfork()ฟังก์ชั่นช่วยเหลือ


7

คนส้อม :

กระบวนการลูกถูกสร้างขึ้นด้วยเธรดเดียว - หนึ่งที่เรียกว่าส้อม () พื้นที่แอดเดรสเสมือนทั้งหมดของพาเรนต์ถูกเรพลิเคทในชายด์รวมถึงสถานะของ mutexes ตัวแปรเงื่อนไขและอ็อบเจ็กต์ pthreads อื่น ๆ การใช้ pthread_atfork (3) อาจมีประโยชน์สำหรับการจัดการกับปัญหาที่อาจทำให้เกิด


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

ดีว่าทำไมมันเป็นคำถามที่แตกต่างกันโดยสิ้นเชิง ฉันไม่รู้การตัดสินใจออกแบบดั้งเดิมที่นำไปสู่การใช้งานนั้น หากคุณสนใจคุณควรถามคำถามนั้นเป็นคำถามแยกต่างหาก
kaylum

@dip แต่สแต็กของเธรดอื่นไม่ถูกคัดลอกใครบอกว่าเป็นเช่นนั้น
Jean-Baptiste Yunès

1
@ Jean-BaptisteYunèsในระบบยูนิกซ์มีโครงสร้างที่แสดงถึงหน่วยความจำเสมือนสำหรับกระบวนการ นั่นคือสิ่งที่ถูกคัดลอก ไม่ใช่แค่ heap และ bss

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

4

จาก The Open Group Base Specifications ฉบับที่ 7, 2018 edition ส้อม :

กระบวนการจะถูกสร้างขึ้นด้วยเธรดเดียว หากกระบวนการแบบมัลติเธรดเรียกfork ()กระบวนการใหม่จะต้องมีเรพลิกาของเธรดการโทรและพื้นที่แอดเดรสทั้งหมดซึ่งอาจรวมถึงสถานะของ mutexes และทรัพยากรอื่น ๆ ดังนั้นเพื่อหลีกเลี่ยงข้อผิดพลาดกระบวนการลูกอาจดำเนินการการดำเนินการแบบ async-signal-safe จนกว่าจะถึงเวลาที่เรียกใช้ฟังก์ชันexecอย่างใดอย่างหนึ่ง

เมื่อแอ็พพลิเคชันเรียกfork ()จากตัวจัดการสัญญาณและ fork fork ใด ๆ ที่ลงทะเบียนโดยpthread_atfork ()เรียกใช้ฟังก์ชันที่ไม่เป็น async-signal-safe ลักษณะการทำงานจะไม่ได้กำหนดไว้


-2

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

แน่นอนว่าเมื่อการจัดการหน่วยความจำมีความละเอียดมากขึ้นชุดรูปแบบนี้ได้รับการแก้ไขเพื่อให้เหมาะกับสภาพแวดล้อมใหม่


สงสัยว่าทำไมสิ่งนี้ถึงถูกโหวต นี่คือวิธีที่ Unix ทำ
Hot Licks

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