ทำไมเราต้องแยกเพื่อสร้างกระบวนการใหม่


95

ใน Unix ทุกครั้งที่เราต้องการสร้างกระบวนการใหม่เราแยกกระบวนการปัจจุบันสร้างกระบวนการลูกใหม่ซึ่งเหมือนกับกระบวนการแม่ จากนั้นเราทำการเรียกระบบ exec เพื่อแทนที่ข้อมูลทั้งหมดจากกระบวนการหลักด้วยกระบวนการนั้นสำหรับกระบวนการใหม่

เหตุใดเราจึงสร้างสำเนาของกระบวนการหลักในตอนแรกและไม่สร้างกระบวนการใหม่โดยตรง


คำตอบ:


61

คำตอบสั้น ๆ คือforkอยู่ในระบบ Unix เพราะง่ายต่อการปรับให้เข้ากับระบบที่มีอยู่ในขณะนั้นและเพราะระบบรุ่นก่อนที่ Berkeleyใช้แนวคิดของส้อม

จากวิวัฒนาการของระบบแบ่งปันเวลา Unix ( เน้นข้อความที่เกี่ยวข้อง):

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

1) การขยายตารางกระบวนการ

2) การเพิ่ม fork fork ที่คัดลอกกระบวนการปัจจุบันไปยังพื้นที่ swap disk โดยใช้ primitive swap IO ที่มีอยู่แล้วและทำการปรับเปลี่ยนบางอย่างในตารางกระบวนการ

ในความเป็นจริงการเรียก fork ของ PDP-7 ต้องการรหัสแอสเซมบลี 27 บรรทัดอย่างแม่นยำ แน่นอนว่าต้องมีการเปลี่ยนแปลงอื่น ๆ ในระบบปฏิบัติการและโปรแกรมผู้ใช้และบางโปรแกรมก็ค่อนข้างน่าสนใจและไม่คาดคิด แต่fork-exec แบบรวมจะมีความซับซ้อนมากขึ้นถ้าเพียงเพราะ exec เช่นนี้ไม่มีอยู่จริง ฟังก์ชั่นของมันได้รับการดำเนินการแล้วโดยใช้ IO ที่ชัดเจนโดยเปลือก

ตั้งแต่กระดาษนั้น Unix ได้วิวัฒนาการ forkตามด้วยexecไม่มีวิธีเดียวที่จะเรียกใช้โปรแกรมอีกต่อไป

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

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


5
คำตอบที่ดี แต่ฉันจะเพิ่ม vfork ที่ไม่ควรใช้อีกต่อไป ความแตกต่างด้านประสิทธิภาพนั้นเล็กน้อยในตอนนี้และการใช้งานอาจเป็นอันตรายได้ ดูคำถาม SO นี้ stackoverflow.com/questions/4856255/ …ไซต์นี้ewontfix.com/7และ "Advanced Unix Programming" หน้า 299 เกี่ยวกับ vfork
Raphael Ahrens

4
machinations (การตั้งค่าโครงสร้างข้อมูล) จำเป็นต้องใช้posix_spawn()ในการทำงานการวางท่อแบบ post-fork เดียวกับที่สามารถทำได้อย่างง่ายดายโดยใช้fork()และรหัสแบบอินไลน์ทำให้อาร์กิวเมนต์ที่น่าสนใจสำหรับfork()การใช้งานง่ายขึ้นมาก
Jonathan Leffler

34

[ฉันจะทำซ้ำส่วนหนึ่งของคำตอบจากที่นี่ ]

ทำไมไม่เพียงแค่มีคำสั่งที่สร้างกระบวนการใหม่ตั้งแต่เริ่มต้น? มันไร้สาระและไม่มีประสิทธิภาพในการทำสำเนาที่จะถูกแทนที่ทันทีหรือไม่?

ในความเป็นจริงแล้วนั่นอาจจะไม่ได้มีประสิทธิภาพเท่าเหตุผล:

  1. "คัดลอก" ผลิตโดยfork()เป็นบิตของนามธรรมตั้งแต่เคอร์เนลใช้สำเนาเมื่อเขียนระบบ ; สิ่งที่ต้องสร้างจริงๆคือแผนที่หน่วยความจำเสมือน หากการคัดลอกโทรออกโดยทันทีข้อมูลexec()ส่วนใหญ่ที่จะถูกคัดลอกหากถูกแก้ไขโดยกิจกรรมของกระบวนการไม่จำเป็นต้องคัดลอก / สร้างจริงเพราะกระบวนการไม่ทำสิ่งใด ๆ ที่ต้องการการใช้งาน

  2. แง่มุมที่สำคัญต่าง ๆ ของกระบวนการลูก (เช่นสภาพแวดล้อม) ไม่จำเป็นต้องมีการทำซ้ำหรือตั้งเป็นรายบุคคลโดยอาศัยการวิเคราะห์ที่ซับซ้อนของบริบท ฯลฯ พวกเขาจะสันนิษฐานว่าเหมือนกับกระบวนการเรียกและ นี่คือระบบที่ใช้งานง่ายที่เราคุ้นเคย

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

ของหลักสูตรที่ไม่ได้อยู่บนพื้นผิวให้ใช้สำเนาเพิ่มเติมที่มีประสิทธิภาพกว่าการใช้กระดานชนวนที่ว่างเปล่า - ยกเว้น "ชนวนว่างเปล่า" ไม่ได้เป็นตัวอักษรอะไรและต้องเกี่ยวข้องกับการจัดสรร ระบบอาจมีเทมเพลตกระบวนการว่าง / ใหม่ทั่วไปที่คัดลอกในลักษณะเดียวกัน1แต่นั่นจะไม่บันทึกอะไรเลยเทียบกับส้อมคัดลอกเมื่อเขียน ดังนั้น # 1 เพียงแสดงให้เห็นว่าการใช้กระบวนการว่างเปล่า "ใหม่" จะไม่มีประสิทธิภาพมากขึ้น

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

1. กลยุทธ์ที่อาจไม่เป็นไปตามตัวอักษร แต่ประเด็นของฉันคือการสร้างกระบวนการเกี่ยวข้องมากกว่าการคัดลอกอิมเมจลงในหน่วยความจำจากดิสก์


3
แม้ว่าจุดทั้งสองจะเป็นจริง แต่ก็ไม่สนับสนุนว่าทำไมจึงเลือกวิธีการฟอร์กกิ้งแทนการสร้างกระบวนการใหม่จากการปฏิบัติการที่ได้รับ
SkyDan

3
ฉันคิดว่านี่จะตอบคำถาม Fork ถูกใช้เพราะในกรณีที่การสร้างกระบวนการใหม่เป็นวิธีที่มีประสิทธิภาพมากที่สุดค่าใช้จ่ายของ fork แทนที่จะเป็นเรื่องเล็กน้อย (น่าจะน้อยกว่า 1% ของต้นทุนการสร้างกระบวนการ) ในทางกลับกันมีหลายสถานที่ที่ fork มีประสิทธิภาพมากกว่าหรือง่ายกว่า API มาก (เช่นการจัดการที่จับไฟล์) การตัดสินใจที่ Unix ทำขึ้นเพื่อรองรับเพียงหนึ่ง API ทำให้ข้อมูลจำเพาะง่ายขึ้น
Cort Ammon

1
@SkyDan คุณพูดถูกมันเป็นคำตอบว่าทำไมไม่ใช่มากกว่าเพราะเหตุใด Mark Plotnick ตอบสนองโดยตรงมากกว่า - ซึ่งฉันจะแปลความหมายไม่ใช่แค่ว่านี่เป็นตัวเลือกที่ง่ายที่สุด แต่ก็อาจเป็นวิธีที่มีประสิทธิภาพที่สุดตัวเลือก (ตามการอ้างอิงของเดนนิสริชชี่: "การเรียก PDP-7 จำเป็นต้องใช้ชุดประกอบ 27 บรรทัดอย่างแม่นยำ ... exec เช่นนี้ไม่มีอยู่; หน้าที่ของมันทำงานแล้ว") ดังนั้นนี่ "ทำไมไม่" คือจริงๆครุ่นคิดเกี่ยวกับสองกลยุทธ์ประเด็นหนึ่งเผิน ๆจะปรากฏขึ้นง่ายขึ้นและมีประสิทธิภาพมากขึ้นเมื่อบางทีมันอาจจะไม่ได้ (เป็นสักขีพยานในชะตากรรมที่น่าสงสัยของ ...
Goldilocks

1
Goldilocks ถูกต้อง มีสถานการณ์ที่การฟอร์กและการปรับเปลี่ยนนั้นถูกกว่าการสร้างขึ้นใหม่ตั้งแต่เริ่มต้น แน่นอนที่สุดตัวอย่างคือเวลาใดก็ตามที่คุณต้องการแยกพฤติกรรม fork()สามารถทำได้อย่างรวดเร็ว (ตามที่ระบุไว้ในคำสั่งของแอสเซมบลี 27 บรรทัด) มองไปในทิศทางอื่นถ้าคุณต้องการ "สร้างกระบวนการตั้งแต่เริ่มต้น" fork()เสียค่าใช้จ่ายเพียงเล็กน้อยมากกว่าการเริ่มต้นจากกระบวนการสร้างที่ว่างเปล่า (27 บรรทัดของการประกอบ + ค่าใช้จ่ายในการจัดการไฟล์ปิด) ดังนั้นforkจัดการทั้งส้อมและสร้างดีในขณะที่createสามารถจัดการสร้างได้ดีเท่านั้น
Cort Ammon

2
คำตอบของคุณอ้างถึงการปรับปรุงฮาร์ดแวร์: หน่วยความจำเสมือนคัดลอกเมื่อเขียน ก่อนหน้านี้forkคัดลอกหน่วยความจำกระบวนการทั้งหมดจริง ๆ และมีราคาแพงมาก
Barmar

6

ฉันคิดว่าเหตุผลที่ Unix มีเพียงforkฟังก์ชั่นในการสร้างกระบวนการใหม่เป็นผลมาจากปรัชญา Unix

พวกเขาสร้างฟังก์ชั่นเดียวที่ทำได้ดี มันสร้างกระบวนการลูก

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

ดังนั้นคุณจะได้รับอิสรภาพที่มากขึ้นเนื่องจากคุณสามารถใช้งานได้

  1. ส้อมโดยไม่ต้อง exec *
  2. ส้อมกับ exec * หรือ
  3. เพียง exec * โดยไม่ต้องแยก

และนอกจากนี้คุณต้องจดจำforkและexec*เรียกใช้ฟังก์ชันซึ่งในปี 1970 คุณต้องทำ


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

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

5

มีปรัชญาสองประการในการสร้างกระบวนการคือ: fork with มรดกและสร้างด้วยอาร์กิวเมนต์ ยูนิกซ์ใช้ส้อมอย่างเห็นได้ชัด (เช่น OSE และ VMS ใช้วิธีการสร้าง) Unix มีลักษณะที่สืบทอดได้มากมายและได้รับการเพิ่มเป็นระยะ ๆ ด้วยการสืบทอดคุณสมบัติใหม่เหล่านี้สามารถเพิ่มได้โดยไม่ต้องเปลี่ยนโปรแกรมที่มีอยู่! การใช้โมเดลสร้างด้วยข้อโต้แย้งการเพิ่มคุณสมบัติใหม่จะหมายถึงการเพิ่มอาร์กิวเมนต์ใหม่ให้กับการเรียกสร้าง รุ่น Unix นั้นง่ายกว่า

นอกจากนี้ยังมีรูปแบบ fork-without-exec ที่มีประโยชน์สูงซึ่งกระบวนการสามารถแบ่งตัวเองออกเป็นหลาย ๆ ชิ้นได้ สิ่งนี้มีความสำคัญยิ่งเมื่อไม่มี async I / O รูปแบบและมีประโยชน์เมื่อใช้ประโยชน์จาก CPU หลายตัวในระบบ (พรี - เธรด) ฉันทำสิ่งนี้มาหลายปีแม้กระทั่งเมื่อไม่นานมานี้ ในสาระสำคัญจะช่วยให้คอนเทนเนอร์ 'โปรแกรม' หลายรายการเป็นโปรแกรมเดียวดังนั้นจึงไม่มีช่องว่างสำหรับการทุจริตหรือรุ่นที่ไม่ตรงกัน ฯลฯ

โมเดล fork / exec ยังช่วยให้เด็กสามารถระบุสภาพแวดล้อมที่แปลกประหลาดอย่างรุนแรงตั้งค่าระหว่าง fork และ exec สิ่งที่ต้องการอธิบายไฟล์โดยเฉพาะอย่างยิ่ง (ส่วนขยายของ stdio fd.) โมเดลการสร้างไม่ได้ให้ความสามารถในการสืบทอดสิ่งที่ผู้สร้างการโทรสร้างไม่ได้จินตนาการ

บางระบบยังสามารถรองรับการคอมไพล์โค้ดเนทีฟแบบไดนามิกซึ่งกระบวนการนี้มีผลในการเขียนโปรแกรมเนทีฟโค้ดของตัวเอง กล่าวอีกนัยหนึ่งมันต้องการโปรแกรมใหม่ที่กำลังเขียนตัวเองโดยไม่ต้องผ่านซอร์สโค้ด / คอมไพเลอร์ / วงจร / linker และใช้พื้นที่ดิสก์ (ฉันเชื่อว่ามีระบบภาษา Verilog ที่ทำสิ่งนี้) fork model สนับสนุนสิ่งนี้, model model ปกติจะไม่


ตัวอธิบายไฟล์ไม่ใช่“ ส่วนขยายของ stdio”; พอยน์เตอร์ของไฟล์ stdio เป็นตัวล้อมรอบตัวอธิบายไฟล์ ตัวให้คำอธิบายไฟล์มาก่อนและเป็นตัวจัดการ Unix I / O พื้นฐาน แต่มิฉะนั้นนี่เป็นจุดที่ดี
สกอตต์

2

ฟังก์ชั่น fork () ไม่เพียง แต่คัดลอกกระบวนการพ่อ แต่คืนค่าซึ่งอ้างว่ากระบวนการเป็นกระบวนการพ่อหรือลูกชายภาพด้านล่างอธิบายถึงวิธีการใช้ fork () เป็นพ่อและ ลูกชาย:

ป้อนคำอธิบายรูปภาพที่นี่

ตามที่แสดงเมื่อกระบวนการคือ fork fork () ส่งคืน ID กระบวนการของ son PID อื่นที่ส่งคืน0

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

ดังนั้นไม่เรียกใช้สำเนาของกระบวนการไม่ใช่สิ่งที่แน่นอนเป็นทางแยก ()


5
แม้ว่ามันจะเป็นจริง แต่สิ่งนี้ไม่ได้ตอบคำถาม เหตุใดการฟอร์กจึงจำเป็นสำหรับการสร้างโปรเซสหากฉันต้องการรันไฟล์สั่งการที่แตกต่างกัน
SkyDan

1
ฉันเห็นด้วยกับ SkyDan - นี่ไม่ตอบคำถาม posix_spawnเป็นรุ่นที่ค่อนข้างแปลกใจกว่าที่คิดไว้เมื่อ 30 ปีที่แล้ว (ก่อนที่จะมี Posix อยู่) เป็นฟังก์ชันfork_execve ; หนึ่งที่สร้างกระบวนการใหม่เริ่มต้นภาพจากปฏิบัติการได้โดยไม่ต้องบอกใบ้แม้กระทั่งการคัดลอกภาพของกระบวนการหลัก (ยกเว้นรายการอาร์กิวเมนต์สภาพแวดล้อมและคุณลักษณะกระบวนการ (เช่นไดเรกทอรีการทำงาน)) และส่งกลับ PID ของกระบวนการใหม่ในการโทร (การปกครอง)
สกอตต์

1
มีวิธีอื่นในการส่งผ่านข้อมูล "หลัก" ไปยังเด็ก เทคนิคการคืนค่าเกิดขึ้นเป็นวิธีที่มีประสิทธิภาพที่สุดในการทำfork หากคุณคิดว่าคุณต้องการforkตั้งแต่แรก
Cort Ammon

0

การเปลี่ยนเส้นทาง I / O นั้นทำได้ง่ายที่สุดหลังจาก fork และก่อน exec เด็กที่รับรู้ว่าเป็นเด็กสามารถปิดตัวให้คำอธิบายไฟล์เปิดตัวใหม่ dup () หรือ dup2 () พวกเขาเพื่อให้พวกเขาใส่หมายเลข fd ที่ถูกต้องและอื่น ๆ ทั้งหมดโดยไม่มีผลกับผู้ปกครอง หลังจากทำเช่นนั้นและอาจมีการเปลี่ยนแปลงตัวแปรสภาพแวดล้อมที่ต้องการ (รวมถึงไม่มีผลกับผู้ปกครอง) ก็สามารถดำเนินการโปรแกรมใหม่ในสภาพแวดล้อมที่เหมาะ


สิ่งที่คุณทำที่นี่คือการทำซ้ำคำตอบที่สามของJim Catheyด้วยรายละเอียดเพิ่มเติมเล็กน้อย
สกอตต์

-2

ฉันคิดว่าทุกคนที่นี่รู้ว่า fork ทำงานอย่างไร แต่คำถามคือทำไมเราต้องสร้างสำเนาที่ซ้ำกันของ parent โดยใช้ fork? Answer ==> นำตัวอย่างของเซิร์ฟเวอร์ (โดยไม่ต้องแยก) ในขณะที่ client-1 กำลังเข้าถึงเซิร์ฟเวอร์หากในเวลาเดียวกันไคลเอนต์ที่สองมาถึง 2 และต้องการเข้าถึงเซิร์ฟเวอร์ แต่เซิร์ฟเวอร์ไม่อนุญาตให้ผู้ที่เพิ่งมาถึง ไคลเอนต์ -2 เนื่องจากเซิร์ฟเวอร์ไม่ว่างให้บริการไคลเอนต์ -1 ดังนั้นไคลเอนต์ -2 ต้องรอหลังจากบริการทั้งหมดไปยังไคลเอนต์ -1 เสร็จสิ้นไคลเอนต์ -2 จะสามารถเข้าถึงเซิร์ฟเวอร์ได้ตอนนี้ให้พิจารณาว่าในเวลาเดียวกัน ไคลเอนต์ -3 มาถึงดังนั้นไคลเอนต์ -3 ต้องรอจนกว่าบริการทั้งหมดไปยังไคลเอนต์ -2 เสร็จสิ้นใช้สถานการณ์ที่ลูกค้าหลายพันคนจำเป็นต้องเข้าถึงเซิร์ฟเวอร์ในเวลาเดียวกัน ... จากนั้นลูกค้าทุกคนจะต้อง รอ (เซิร์ฟเวอร์ไม่ว่าง !!)

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


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