วันพฤหัสบดีที่ 6 มีนาคม พ.ศ. 2551

บทที่2 โปรเซส และ Thread

บทที่ 2โปรเซส และ Thread
การศึกษาเรื่องโปรเซส เป็นหัวใจของการทำความเข้าใจของระบบคอมพิวเตอร์ที่มีผู้ใช้หลายคน ( multiuser computer system ) คำว่าโปรเซสถูกใช้ครั้งแรกโดยผู้ออกแบบระบบมัลติกส์ ( multics ) ในทศวรรษ 1690 มีการให้ความหมายของคำว่า "โปรเซส" ไว้หลายความหมายเช่น
- โปรแกรมที่กำลังถูกเอ็กซีคิ้ว
- กิจกรรมที่มีการทำงานสัมพันธ์กัน
- สิ่งที่ถูกมอบหมายไปให้โปรเซสเซอร์ได้
- หน่วยซึ่งถูกส่งต่อได้ ( dispatchable )
ยังไม่มีความหมายใดที่เป็นที่ยอมรับกันทุกคน แต่ความหมายที่ว่า โปรเซส คือ "โปรแกรมที่กำลังถูกเอ็กซีคิ้ว" นั้นถูกใช้บ่อยมากที่สุด ดังนั้นจึงเอาความหมายนี้เป็นความหมายของคำว่า โปรเซส เราอาจเปรียบเทียบโปรแกรมเหมือนกับรถยนต์ที่จอดนิ่งอยู่ที่พร้อมที่จะวิ่งไป ในระบบหลายโปรแกรม ( multiprogramming ) โปรเซสอาจเปรียบกับรถยนต์ที่วิ่งออกจากจุดเริ่มต้น ถ้ามีหลายโปรเซสอยู่ในระบบก็เหมือนกับการที่เรามีรถหลายคันที่จะต้องออกวิ่ง ไปพร้อม ๆ กัน ตัวซีพียูเปรียบได้กับคนขับรถ ถ้าซีพียูมีตัวเดียวก็เหมือนกับคนขับรถมีเพียงคนเดียว ดังนั้นเมื่อรถหลายคันออกวิ่งการที่คนขับคนเดียวจะพารถหลายๆ คันวิ่งไปต้องขับรถทีละคันให้วิ่งเดินหน้าไปทีละนิด เวียนเปลี่ยนไปจนครบทุกคัน จนถึงจุดหมายปลายทาง ( โปรแกรมสิ้นสุดลง ) นั้นคือเราสามารถมีโปรเซสหลายๆ โปรเซสทำงานไปพร้อมๆ กันได้โดยมีซีพียูเพียงตัวเดียว
2.1องค์ประกอบของโปรเซส
1. ชื่อและหมายเลขประจำตัว (process ID) ของโปรเซส ซึ่งต้องไม่ซ้ำกับโปรเซสอื่น
2. โค้ดของโปรแกรม (program code) เป็นคำสั่งที่สามารถเอ็กซีคิ้วได้ทันที (ภาษาเครื่อง)
3. ข้อมูล (data) ที่โปรแกรมต้องการหรือจัดการ ข้อมูลนี้อาจเป็นของโปรเซสใดโปรเซส
หนึ่ง หรืออาจใช้ได้ร่วมกันกับโปรเซสอื่นๆ ก็ได้
4. บล็อกควบคุมโปรเซส (process control block) หรือ PCB OS กำหนดเนื้อที่บาง
ส่วนในหน่วยความจำเพื่อทำเป็น PCB PCB เป็นโครงสร้างข้อมูลชนิดหนึ่งซึ่งเก็บข้อมูลที่สำคัญๆ ของโปรเซสนั้นๆ เอาไว้ ข้อมูลเหล่านี้ได้แก่
4.1 พอยเตอร์ (Pointer)
4.2 สถานะของโปรเซส (Process state)
4.3 หมายเลขโปรเซส (Program id)
4.4 ตัวนับจำนวน (Program counter)
4.5 รีจิสเตอร์ (Register)
4.6 ข้อมูลการจัดเวลาของซีพียู (CPU scheduling information)
4.7 ข้อมูลการจัดการหน่วยความจำ (Memory management information)
4.8 ข้อมูลแอ็กเคาต์ (Account information)
4.9 ข้อมูลสถานะอินพุต/เอาต์พุต (I/O status information)
5. PSW (program status words) เป็นตัวควบคุมลำดับการเอ็กซีคิ้วคำสั่งของโปรเซส และยังเก็บข้อมูลเกี่ยวกับสถานะของโปรเซส แอดเดรสของคำสั่งต่อไปที่จะถูกเอ็กซีคิ้วจะถูกเก็บไว้ใน PSW PSW นี้จึงมีหน้าที่คล้ายๆ กับโปรแกรมเคาน์เตอร์บนเครื่องไมโครคอมพิวเตอร์
6. คุณสมบัติของโปรเซส ได้แก่
6.1 ลำดับความสำคัญ (Priority) ของโปรเซส โปรเซสแต่ละตัวจะถูกกำหนดความสำคัญขึ้นขณะที่โปรเซสถูกสร้างขึ้น ความสำคัญนี้อาจเปลี่ยนแปลงได้หรือไม่ได้สุดแล้วแต่ OS โปรเซสที่มีความสำคัญมาก OS ก็จะให้สิทธิพิเศษมากกว่าโปรเซสที่มีความสำคัญน้อย เช่น ให้เวลาของซีพียูนานกว่า (ให้ครอบครองซีพียูได้นานกว่า)
6.2 อำนาจหน้าที่ (authority) เป็นสิ่งที่บ่งบอกว่าโปรเซสนั้นๆ สามารถทำอะไรได้บ้าง ใช้อุปกรณ์ชิ้นไหนได้บ้างเป็นต้น ตัวอย่างเช่นโปรเซส A ห้ามใช้ดิสก์ใดๆ ทั้งสิ้นแต่สามารถรับข้อมูลจากทุกๆ โปรเซสในระบบได้
6.3 คุณสมบัติอื่นๆ ที่ OS จะกำหนดให้มี
2.2 สถานะของโปรเซส
สถานะของโปรเซสแบ่งได้ 6 สถานะ
ในขณะที่โปรเซสกำลังถูกประมวลผลอยู่นั้น โปรเซสอาจมีการเปลี่ยนสถานะก็ได้ การกำหนดสถานะของโปรเซสจะเป็นไปตามกิจกรรมที่กำลังดำเนินการอยู่ในขณะนั้น แต่ละโปรเซสอาจมีสถานะต่อไปนี้ 1. สถานะเริ่มต้น(New) เป็นสถานะที่เริ่มต้นเมื่อสร้างโปรเซสขึ้นมา 2. สถานะพร้อม(Ready) เป็นสถานะที่พร้อมจะครอบครอง CPU ในทันทีที่ระบบปฏิบัติการมอบหมายงานให้ สถานะนี้จะยังไม่มีการรันโปรเซส เพียงแต่หยุดนิ่งรอเท่านั้น 3. สถานะรัน หรือสถานะทำงาน(Running) เป็นสถานะที่โปรเซสที่ครอบครอง CPU อยู่แล้วมีการรันนั้นโดยมีการประมวลผลคำสั่งในโปรแกรมของโปรเซส4. สถานะรอ(Wait) เป็นสถานที่ที่โปรเซสกำลังรอเหตุการณ์บางอย่างให้เกิดขึ้นก่อน เช่นการจัดการ I/O ก่อน หรืออาจจะเป็นการรอสัญญาณ 5. สถานะบล็อก(Block) เป็นสถานะที่อาจจะต้องการใช้อุปกรณ์ I/O หรือเกิดอินเทอร์รัพต์ ระหว่างที่รันโปรเซส จะต้องมีการรอเพื่อให้มีการจัดการอุปกรณ์ I/O หรือจัดการเทอร์รัพต์ให้เรียบร้อยก่อนที่จะกลับไปสถานะรันได้ต่อไป 6. สถานะสิ้นสุด(Terminate)เป็นสถานะที่หยุดนิ่งเนื่องมาจากโปรเซสถูกประมวลผลเสร็จหมดแล้ว
สถานะของโปรเซสแบ่งได้อีกแบบมี 4 สถานะ
1. สถานะพร้อม (ready state) คือสถานะที่โปรเซสพร้อมที่จะใช้ซีพียูทันทีที่ระบบปฏิบัติการมอบหมายให้ ในสถานะนี้ไม่มีการรันของโปรเซส
2. สถานะรัน (running state) คือสถานะที่โปรเซสกำลังครอบครองซีพียูอยู่ มีการรันของโปรเซสจริงๆ เพราะโปรเซสใช้ซีพียูเอ็กซีคิ้วคำสั่ง หรือโค้ดโปรแกรมของโปรเซสนั้น
3. สถานะติดขัด (blocked state) คือสถานะที่โปรเซสหยุดรอเหตุการณ์ใดเหตุการณ์หนึ่งให้เกิดขึ้น โปรเซสไม่จำเป็นต้องใช้ซีพียูและยังไม่พร้อมที่จะครอบครองซีพียู ซึ่งจะทำให้
โปรเซสอื่นเข้ามาครอบครองซีพียูในช่วงนี้ได้
4. สถานะพัก (suspend state) คือสถานะที่โปรเซสไม่มีการทำงานใดๆ หยุดนิ่งอย่างสมบูรณ์ ไม่มีการรอการใช้ซีพียูหรือเหตุการณ์ใดๆ ให้เกิดขึ้น
2.3การจัดเวลาโปรเซส
ใช้ในระบบมัลติโปรแกรมมิ่ง คือการจัดโปรเซสให้รันตลอดเวลา เพื่อให้ใช้ประโยชน์ซีพียูได้สูงสุด
โปรเซสที่ระบบปฏิบัติการสร้างขึ้นมาใหม่จะอยู่นสถานะพร้อมและเก็บ อยู่ในคิว เรียกว่า Ready Queue เพื่อรอการรัน
ต้องพิจารณาหน่วยความจำของระบบมีเพียงพอหรือไม่
Ready Queue จะเก็บโปรเซสในลักษณะลิงค์ลิสต์ (Link list) ที่ส่วนหัวของคิว จะประกอบด้วยพอยเตอร์ของ PCB เริ่มต้นและท้ายสุดของลิสต์ และแต่ละ PCB จะมีพอยเตอร์ชี้ไปยัง PCB ตัวต่อไปของคิว

รูป 2.3 คิวที่พร้อมทำงานและอินพุต/เอาต์พุตอื่น ๆ


รูป2.4 เปลี่ยนสถานะของโปรเซสสั้นๆ
2.3.1 ดีไวซ์คิว(Device Queue) สำหรับคิวของโปรเซสที่รอการตอบสนองจากการใช้อุปกรณ์อินพุต/เอาต์พุตเรียกว่า “ดีไวซ์คิว” ซึ่งอุปกรณ์แต่ละอันจะมีคิวเป็นของตนเอง ที่มีพอยเตอร์เก็บส่วนหัวและส่วนท้ายของ PCB ที่เรียกใช้อุปกรณ์นี้ และในส่วนของ PCB ก็จะมีพอยเตอร์ที่บอกว่า PCB ใดเป็นโปรเซสต่อไปที่จะรัน
รูป2.7 การจัดคิวของโปรเซส
2.3.2 คอนเท็กซ์สวิตช์(Context Switch) เมื่อ CPU รันโปรเซสจนเสร็จเรียบร้อยแล้วจะต้องมีการสวิตช์ หรือสลับไปยังโปรเซสในคิวต่อไป การสวิตช์นี้เรียกว่าคอนแท็กซ์สวิตช์ ในช่วงที่ทำการสวิตช์จะไม่มีการทำงานใดๆ ส่วนเวลาที่ใช้ในการสวิตช์จะแตกต่างไปตามเครื่อง เช่นความเร็วของหน่วยเก็บความจำ, จำนวนรีจิสเตอร์ที่ถูกกอปปี้และคำสั่งพิเศษที่มีอยู่ในระบบ โดยทั่วไปความเร็วจะอยู่ระหว่าง 1-1000 ไมโครวินาที จะเห็นว่าการสวิตช์จะขึ้นอยู่กับประสิทธิภาพของเครื่อง และเมื่อเครื่องคอมพิวเตอร์มีอุปกรณ์พิเศษอย่างเช่นมีหลายรีจิสเตอร์ หรือมีหลาย CPU การจัดการอุปกรณ์เหล่านี้ได้ต้องมีระบบปฏิบัติการที่ดีด้วย และเนื่องจากข้อจำกัดของอุปกรณ์ฮาร์ดแวร์ทำให้เกิดปัญหาคอขวดขึ้น เพื่อแก้ไขปัญหานี้จึงมีการเพิ่มประสิทธิภาพโครงสร้างใหม่ที่เรียกว่า Thread ขึ้นมา
2.4 โอเปอเรชันของโปรเซส
โปรเซสต่างๆ ในระบบที่เอ็กซิคิวได้พร้อมกัน จะต้องมีการสร้างและลบตลอดเวลา ระบบปฎิบัติการเป็นตัวสร้างเหล่านี้ โดยทั้งสั่งให้โปรเซสสิ้นสุดโดยใช้กลไกที่น่าสนใจดังนี้
2.4.1การสร้างโปรเซส (Process Creation)
โปรเซสหนึ่ง ๆ อาจสร้างโปรเซสใหม่เกิดขึ้น โดยการใช้คำสั่งเรียกระบบสร้างโปรเซส และโปรเซสใหม่ ๆ ที่เกิดขึ้นมานั้นอาจจะสร้างโปรเซสใหม่ ๆ ต่อไปได้อีก ดังรูป

รูปที่ 2.8 รูปแบบโครงสร้างโปรเซส
โปรเซสที่เป็นผู้สร้าง เรียกว่า โปรเซสแม่ (Parent Process) โปรเซสใหม่ที่ถูกสร้างขึ้นมาเรียกว่า โปรเซสลูก (Children Process) โดยทั่วไป โปรเซสหนึ่ง ๆ จะต้องการทรัพยากร เช่น เวลาที่ใช้ในหน่วยประมวลผลกลาง , หน่วยความจำ , แฟ้มข้อมูล ,อุปกรณ์รับ-ส่งข้อมูล เป็นจำนวนที่แน่นอน เพื่อที่จะทำงานได้จนเสร็จสมบูรณ์ และเมื่อมีโปรเซสย่อยเกิดขึ้น โปรเซสย่อยนั้นอาจร้องขอทรัพยากร ที่ต้องการจากระบบปฏิบัติการได้โดยตรง หรือ ถูกจำกัดให้ใช้ได้เฉพาะทรัพยากรส่วนของทรัพยากรแม่เท่านั้น ดังนั้น โปรเซสแม่ต้องแบ่งทรัพยากรให้โปรเซสย่อยแต่ละตัว หรือ ให้โปรเซสย่อยเหล่านั้น ใช้ทรัพยากรร่วมกัน (เช่น แฟ้มข้อมูล หรือ หน่วยความจำ) หรือ ให้โปรเซสย่อยใช้ทรัพยากรส่วนเฉพาะของแม่ (ซึ่งเป็นการป้องกันไม่ให้ระบบถูกแย่งทรัพยากรไปทั้งหมด เนื่องจากมีบางโปรเซสสร้างโปรเซสย่อยจำนวนมากเกินไป) หลังจากสร้างโปรเซสย่อยแล้ว โปรเซสแม่อาจทำงาน (execute) ได้ 2 วิธี คือ– โปรเซสแม่ ทำงานพร้อม ๆ กัน (concurrent) ไปกับโปรเซสลูก โปรเซสแม่คอยจนกระทั่ง โปรเซสลูกทั้งหมด สิ้นสุดการทำงาน ในการระบุพื้นที่ว่างของโปรเซสใหม่ทำได้ 2 วิธี คือ– โปรเซสลูกทำสำเนา (duplicate) มาจากโปรเซสแม่ (จำลองมา)– โปรเซสลูกมีโปรแกรมที่ถูก load เข้ามาเอง (สร้างเอง) ในระบบปฏิบัติการ UNIX แต่ละโปรเซสจะมีเลขประจำตัวเฉพาะ (Process Identifier) เป็นเลขจำนวนเต็ม (Integer) โปรเซสจะสร้างโปรเซสย่อย โดยคำสั่งเรียกระบบ fork โปรเซสใหม่ที่เกิดขึ้น จะมีตำแหน่งโปรแกรมของโปรเซสเดิม ซึ่งช่วยให้โปรเซสแม่(เดิม) สามารถติดต่อสื่อสารกับโปรเซสลูก (ใหม่) ได้สะดวก โปรเซสทั้งสอง (แม่และลูก) จะทำงานจากคำสั่ง (ในโปรแกรมเดียวกัน) จากคำสั่ง fork โดยที่โปรเซสลูกจะได้รหัสส่งคืนจากคำสั่ง forkเป็นศูนย์แต่โปรเซสแม่จะได้รหัสส่งคืนเป็นตัวเลขแสดงหมายเลขของโปรเซสลูก โดยปกติ คำสั่งหลักจากคำสั่ง fork จะเป็นคำสั่งเรียกระบบ execve ทำหน้าที่นำโปรแกรมจากจานบันทึกมาลงในหน่วยความจำทับโปรแกรมเดิมของโปรเซสที่ใช้คำสั่งนี้ แล้วทำงานต่อในโปรแกรมใหม่โปรเซสแม่สามารถสร้างลูกได้เรื่อยๆหรือถ้าไม่มีอะไรทำในขณะลูกกำลังทำงาน มันจะใช้คำสั่งเรียกระบบ wait เพื่อย้ายตัวเองไปที่แถวพร้อม จนกระทั้งลูกเสร็จสิ้นการทำงาน
2.4.2 การเสร็จสิ้นโปรเซส (Process Termination)
โปรเซสจะสิ้นสุดหรือถูกยกเลิก เมื่อทำงานเสร็จในขั้นสุดท้าย แล้วร้องขอให้ระบบปฏิบัติการลบโปรเซสทิ้งไป โดยใช้คำสั่งเรียกระบบ exit ซึ่งโปรเซสสามารถส่งข้อมูล (output) กลับไปให้โปรเซสแม่ได้ โดยคำสั่งเรียกระบบ wait โปรเซสหนึ่งอาจยกเลิกโปรเซสอื่นได้ โดยใช้คำสั่งเรียกระบบ เช่น คำสั่งยกเลิก (abort) การใช้คำสั่งนี้โดยปกติ ต้องเป็นโปรเซสแม่ใช้กับโปรเซสลูกเท่านั้น (เพราะโปรเซสแม่ทราบหมายเลขของโปรเซสลูกจากเมื่อตอนที่สร้างโปรเซสลูก)โปรเซสแม่อาจ
ต้องการยกเลิกโปรเซสลูกตัวหนึ่งเพราะ- โปรเซสลูกใช้ทรัพยากรที่โปรเซสแม่แบ่งให้จนหมดแล้ว ทรัพยากรไม่พอใช้
- โปรเซสแม่ไม่ต้องการใช้โปรเซสลูกตัวนี้ อีกต่อไป
- โปรเซสแม่เสร็จสิ้นและระบบปฏิบัติการไม่ต้องการให้โปรเซสลูกทำงานต่อ
ระบบส่วนใหญ่ เมื่อโปรเซสแม่สิ้นสุด โปรเซสลูกต้องสิ้นสุดด้วย เราเรียกว่า การยกเลิกแบบลูกโซ่ (Cascading Termination) ซึ่งระบบมักจะเป็นผู้จัดการ ตัวอย่าง ในระบบ UNIX โปรเซสลูกจะสิ้นสุดหรือถูกยกเลิก โดยใช้คำสั่งเรียกระบบ exit ซึ่งโปรเซสแม่จะรอเหตุการณ์นี้ โดยใช้คำสั่งเรียกระบบ wait ซึ่งจะให้ค่ากลับคืนมาเป็นหมายเลขของโปรเซสลูกที่ถูกยกเลิกไป ในระบบ UNIX โปรเซสแม่ไม่จำเป็นต้องแบ่งทรัพยากรให้โปรเซสลูกเลย ระบบจะจัดการให้โดยให้ศักดิ์เท่า ๆ กัน ทุกโปรเซสในการใช้ทรัพยากรในระบบ (เช่น หน่วยความจำหลัก , จานบันทึก)
2.5 โปรเซสสื่อประสาน (Cooperating Process)
โปรเซสจะเป็นโปรเซสสื่อประสานถ้าโปรเซสนั้นมีผลกระทบหรือได้รับผลกระทบจากโปรเซสอื่นที่เอ็กซิคิวต์อยู่ในระบบนั้น อาจกล่าวได้ว่าโปรเซสสื่อประสานจะมีการแชร์ข้อมูลกับโปรเซสอื่นในระบบ โดยระบบปฏิบัติการจะต้องแชร์หน่วยความจำไว้ใช้งาน เนื้อที่หน่วยความจำส่วนนั้นคือบัฟเฟอร์
เหตุที่ทำให้เกิดการประสานระหว่างโปรเซส
การแชร์ข้อมูลข่าวสาร : ผู้ใช้หลายคนต้องการข้อมูลเดียวกัน ในเวลานั้น
การเพิ่มความเร็วในการคำนวณ : โดยการแบ่งโปรแกรมออกเป็นส่วนย่อย ๆ แล้วเอ็กซิคิวต์ ขนานกันไป
ความสะดวก : ผู้ใช้ต้องการทำงานหลายอย่างในเวลาเดียวกัน
กลไกที่สนับสนุนให้โปรเซสสามารถประสานกันได้ คือ การติดต่อระหว่างโปรเซส (InterProcess Communication) และการซินโครไนซ์โปรเซส (Synchronize Process)
การเอ็กซิคิวต์โปรเซสที่มีการประสานกับโปรเซสอื่นจำเป็นต้องใช้บัฟเฟอร์ โดยระบบปฏิบัติการจะต้องแชร์หน่วยความจำไว้ใช้งาน และจะต้องมีกลไกที่สนับสนุนให้สามารถประสานได้ กลไกที่ว่าคือการติดต่อระหว่างโปรเซส (InterProcess Communication : IPC) และการซินโครไนซ์โปรเซส (Synchronize) ซึ่งผู้เขียนจะกล่าวรายละเอียดในหัวข้อต่อไป
2.6 การติดต่อระหว่างโปรเซส (InterProcess Communication)
ในหัวข้อที่ผ่านมา คุณคงได้ทราบเกี่ยวกับการประสานโปรเซส ที่สามารถติดต่อในภาวะที่ใช้บัฟเฟอร์หรือหน่วยความจำ และต้องใช้กลไกคือการติดต่อระหว่างโปรเซส และการซินโครไนซ์โปรเซส สำหรับในหัวข้อนี้จะกล่าวถึงการติดต่อระหว่างโปรเซส หรือ IPC (TnterProcess Communication)
2.6.1 โครงสร้างพื้นฐาน
IPC สนับสนุนกลไกเพื่อให้โปรเซสสามารถติดต่อซึ่งกันและกันได้อย่างมีประสิทธิภาพ ที่เห็นได้ชัดที่สุดคือระบบแมสเสจ (Message system) ฟังก์ชันของระบบแมสเสจที่ IPC สนับสนุนมีอย่างน้อย 2 ประการคือ การส่งแมสเสจ (Send message) และรับแมสเสจ (Receive message) เมื่อโปรเซสใดต้องการแมสเสจจากโปรเซสอื่น จะส่งคำร้องขอไปยังโปรเซสนั้น โปรเซสที่ถูกร้องขอจะส่งแมสเสจนั้นไปให้ ขนาดของข้อมูลอาจจะมีขนาดคงที่ หรือขนาดไม่คงที่ก็ได้ ก่อนกรรับ-ส่งแมสเสจจะต้องมีการสร้างลิงค์ให้พร้อมก่อน ทั้งลิงค์ทางกายภาพ (เช่น การแชร์หน่วยความจำ, บัส หรือเน็ตเวิร์คก็ได้) และลิงค์ทางลอจิก ซึ่งลิงค์ทางลอจิกจะมีคุณสมบัติที่น่าสนใจดังนี้
- จะสร้างลิงค์อย่างไร
- ลิงค์ที่สร้างนั้นสัมพันธ์กับโปรเซสมากกว่า 2 โปรเซสหรือไม่
- ระหว่างโปรเซสทั้งสองจะมีกี่ลิงค์
- ความจุของลิงค์เป็นเท่าไร
- ลิงค์นั้นมีบัฟเฟอร์หรือไม่ ถ้ามีขนาดของบัฟเฟอร์เป็นเท่าไร
- ลิงค์เป็นแบบทางเดียว (unidirectional) หรือสองทิศทาง (bidirectional) โดยที่การลิงคแบบทางเดียวจะให้มีการรับส่งแมสเสจได้ทางเดียว คือโปรเซสในส่งก็ส่งอย่างเดียว สามารถรับได้ หรือโปรเซสใดรับก็รับอย่างเดียวจะส่งไม่ได้ ส่วนกรลิงค์แบบสองทิศทางจะช่วยให้โปรเซสนั้นสามารถรับหรือส่งแมสเสจได้ สำหรับการลิงค์หลายโปรเซสจ้ะองมีอย่างน้อย 1 โปรเซสที่ทำหน้าที่รับแมสเสจ
นอกจากนี้ยังมีอีกหลายวิธีที่แสดงถึงการลิงค์แบบลอจิกและโอเปอเรชันในการรับ-ส่งแมสเสจ ดังนี้
- การติดต่อเป็นแบบทางตรง หรือทางอ้อม
- การติดต่อเป็นแบบสมมาตรหรือไม่สมมาตร
- เป็นแบบอัตโนมัติหรือใช้บัฟเฟอร์เฉพาะแบบ
- ส่งแบบสำเนา หรืออ้างอิง
- แมสเสจมีขนาดคงที่ หรือไม่คงที่
2.6.2 วิธีการติดต่อ
การติดต่อระหว่างโปรเซสอาจจะใช้วิธีส่งทางตรง หรือทางอ้อม (direct/indirect) ก็ได้ โดยทั้ง 2 วิธี มีคุณสมบัติและวิธีการที่น่าสนใจดังนี้
2.6.2.1 การติดต่อทางตรง (direct communication)
การติดต่อแบบนี้แต่ละโปรเซสที่ต้องการติดต่อกันจะต้องกำหนดชื่อเฉพาะที่ใช้ในการติดต่อทั้งผู้รับและผู้ส่ง ยกตัวอย่างเช่น ถ้าต้องการส่งแมสเสจจาก A ไป B จะมารกำหนดรูปแบบคือ

send( B, message) จะเป็นการส่งแมสเสจไปยังโปรเซส B
receive( A, message) จะเป็นการรับแมสเสจจากโปรเซส A

ลิงค์แบบนี้จะมีคุณสมบัติดังนี้
- การสร้างลิงค์จะเป็นแบบอัตโนมัติระหว่างคู่ของโปรเซสที่ต้องการติดต่อ (ในที่นี้คือ A กับ B) โปรเซสจะทราบหายเลขโปรเซสที่จะติดต่อด้วย
- ลิงค์หนึ่งๆ จะมีความสัมพันธ์เฉพาะโปรเซสสองโปรเซสเท่านั้น
- ระหว่างโปรเซสแต่ละคู่นั้นจะมีเพียงลิงค์เดียวเท่านั้น
- ลิงค์นี้เป็นได้ทั้งทิศทางเดียว และสองทิศทาง แต่ปกติจะเป็นแบบสองทิศทาง
วิธีการรับ-ส่งแมสเสจแบบนี้ ระบบปฏิบัติการจะไม่ดำเนินการติดต่อให้กับโปรเซสทั้งสอง โปรเซสทั้งสองจะต้องจัดการเอง ตัวอย่างการส่งแมสเสจจากโปรเซส A ไปโปรเซส B หลังจากสร้างลิงค์เรียบร้อยแล้ว ทั้งโปรเซส A และโปรเซส B จะจองหน่วยความจำที่แชร์ไว้แล้ว (โปรเซสทั้งสองจะทราบว่าหน่วยความจำนั้นอยู่ตำแหน่งใด) โปรเซส A จะนำข้อมูลไปวางบนตำแหน่งของหน่วยความจำที่จองไว้ โปรเซส B จะต้องคอยตรวจสอบว่าโปรเซส A วางข้อมูลหรือยัง ถ้ายังไม่วางก็จะยังไม่ดึงข้อมูล รอจนกระทั่งโปรเซส A วางเรียบร้อยแล้วจึงจะดึงข้อมูลนั้นไปใช้งาน ส่วนโปรเซส A ก็จะต้องตรวจสอบเช่นกันว่าข้อมูลที่ตนเองวางนั้น โปรเซส B ดึงไปใช้งานหรือยัง ถ้ายังไม่ดึง โปรเซส A จะต้องรอก่อน ยังไม่มีการวางข้อมูลใหม่ เพื่อป้องกันการวางข้อมูลใหม่ทัยข้อมูลเดิมซึ่งจะมีผลให้การทำงานไม่สมบูรณ์ (ข้อมูลหายไป) รอจนกระทั่งการดึงข้อมูลเรียบร้อยจึงวางข้อมูลใหม่ได้ ทำเช่นนี้เรื่อยไปจนกว่าข้อมูลจะหมด กลไกที่ใช้ในการตรวจสอบเวลาที่เหมาะสมในการรับ-ส่งข้อมูลนี้เรียกว่า “การซินโครไนซ์โปรเซส” (Process Synchronization) ซึ่งผู้เขียนจะกล่าวรายละเอียดในหัวข้อต่อไป
2.6.2.2 การติดต่อทางอ้อม (indirect communication)
การติดต่อแบบนี้โปรเซสทั้งสองที่ต้องการติดต่อกันจะติดต่อกันผ่านทางเมลล์บ็อกซ์ (Mailbox) หรืออาจเรียกว่าเป็นการติดต่อทางพอร์ต (port) เมลล์บ็อกซ์เป็นออปเจ็กต์ที่เก็บแมสเสจจากโปรเซสหนึ่งเพื่อส่งไปอีกโปรเซสหนึ่ง แต่ละเมลล์บ็อกซ์จะมีหมายเลขไม่ซ้ำกับเมลล์บ็อกซ์อื่น วิธีนี้จะทำให้โปรเซสหนึ่งสามารถติดต่อโปรเซสอื่นผ่านทางเมลล์บ็อกซ์หลายเมลล์บ็อกซ์ที่แตกต่างกันได้ และเมลล์บ็อกซ์ที่จะใช้ในการติดต่อกันนี้จะต้องมีการแชร์เมลล์บ็อกซ์ไว้ก่อนด้วย รูปแบบคำสั่งการรับ-ส่งข้อมูลผ่านเมลล์บ็อกซ์เป็นดังนี้
send( B, message) เป็นการส่งแมสเสจไปยังเมลล์บ็อกซ์ B
receive( A, message) เป็นการรับแมสเสจจากเมลล์บ้อกซ์ A

ลิงค์แบบนี้จะมีคุณสมบัติดังนี้
- จะมีการสร้างลิงค์ระหว่างโปรเซสที่มีการแชร์เมลล์บ็อกซ์เท่านั้น
- ลิงค์หนึ่งๆ อาจจะมีความสัมพันธ์มากกว่าสองโปรเซสได้
- ระหว่างโปรเซสแต่ละคู่นั้นอาจจะมีหลายลิงค์ที่แตกต่างกันได้ แต่ละลิงค์จะมีเพียงเมลล์บ็อกซ์เดียว
- การลิงค์อาจจะเป็นทิศทางเดียว หรือสองทิศทางก็ได้
ตอนนี้เพื่อความเข้าใจมากยิ่งขึ้น สมมุติว่าทั้งโปรเซส P1, P2 และ P3 มีการแชร์เมลล์บ็อกซ์ A ไว้ โปรเซส P1 จะส่งเมสเสจไปยัง A ในขณะที่โปรเซส P2 และ P3 ต้องการรับแมสเสจจาก A คำถามก็คือว่า โปรเซสใดจะรับแมสเสจที่ส่งจาก A คำถามนี้อาจจะแก้ได้หลายวิธี ดังนี้
- ยอมให้มีการลิงค์ทั้งสองโปรเซส
- ยอมให้มีการรับแมสเสจได้เพียงครั้งละ 1 โปรเซส
- ยอมให้ระบบเลือกว่าโปรเซสใดที่จะเข้ารับแมสเสจ (ในที่นี้อาจจะเป็น P2 หรือ P3 ก็ได้ แต่ไม่ใช้ครั้งละสองโปรเซสพร้อมกัน) โดยระบบจะกำหนดผู้รับไปยังผู้ส่งก่อนการส่ง
เมลล์บ็อกซ์แบบคิว โครงสร้างของเมลล์บ็อกซ์แบบนี้เป็นโครงสร้างที่ดึงข้อมูลออกจากเมลล์บ็อกซ์ตามลำดับก่อน-หลังของข้อมูลที่ส่งเข้ามา นั่นคือข้อมูลใดส่งเข้ามาในเมลล์บ็อกซ์ก่อนก็จะถูกดึงออกไปก่อน ส่วนข้อมูลใดส่งเข้ามาภายหลังก็จะถูกดึงออกไปภายหลัง อาจเรียกการทำงานแบบนี้ว่า FIFO (First In First Out) ลักษณะโครงสร้างเมลล์บ็อกซ์แบบคิวเป็นดังรูป 2.9

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

เมลล์บ็อกซ์แบบสแต็ก โครงสร้างของเมลล์บ็อกซ์แบบนี้เป็นโครงสร้างตรงข้ามกับเมลล์บ็อกซ์แบบคิวในการดึงข้อมูล นั่นก็คือข้อมูลใดส่งเข้ามาเมลล์บ็อกซ์ก่อนจะถูกดึงออกไปใช้งานภายหลัง โดยจะนำข้อมูลที่ส่งเข้ามาภายหลังออกไปใช้ก่อน อาจเรียกการทำงานแบบนี้ว่า FILO (First In Last Out) ลักษณะโครงสร้างเมลล์บ็อกซ์แบบสแต็กเป็นดังรูป 2.11

2.6.3 การจัดบัฟเฟอร์
ในการสร้างลิงค์ นอกจากจะเป็นการกำหนดเส้นทางข้อมูลแล้ว ลิงค์ยังมีความจุที่เป็นตัวเลขแสดงจำนวนแมสเสจที่สามารถเก็บไว้ชั่วคราวได้ คุณสมบัตินี้อาจจะมองว่าเป็นคิวของแมสเสจที่ผูกติดลิงค์ก็ได้ โดยพื้นฐานจะมีความจุ 3 ลักษณะ คือ
- ความจุศูนย์ (Zero capacity) ความจุแบบนี้จำให้คิวมีขนาดสูงสุดเป็น 0 ดังนั้นลิงค์จะไม่มีแมสเสจรอยู่เลย ในกรณีนี้ผู้ส่งจะต้องรอจนกว่าผู้รับแมสเสจ โปรเซสทั้งสองจะต้องซินโครไนซ์เพื่อให้เกิดการถ่ายโอนแมสเสจ “rendezvous”
- ความจุแบบมีขอบเขต (Boundd capacity) ความจุแบบี้จะทำให้คิวมีขนาดคงที่เป็น n ดังนั้นจะมีแมสเสจได้สูงสุด n แสเสจที่เก็บในคิวได้ถ้าคิวยังไม่เต็มเมื่อแมสเสจใหม่ถูกส่งเข้ามา หลังจากนั้นก็เข้าไปอยู่ในคิว (แมสเสจนั้นอาจจะถูกก็อปปี้ไว้หรือตำแหน่งพอยเตอร์ของแมสเสจไว้ก็ได้) ในขณะที่ผู้ส่งสามารถเอ็กซิคิวต์ได้ต่อไปโดยไม่ต้องรอ เนื่องจากเป็นความจุที่คงที่ ดังนั้นเมื่อคิวเต็ม ผู้ส่งจะต้องรอจนกว่าจะมีที่ว่างในคิว
- ความจุไม่มีขอบเขต (Unbounded capacity) ความจุแบบนี้ทำให้คิวมีขนาดใหญ่ไม่คงที่ทำให้แมสเสจถูกเก็บไว้ได้เสมอ ผู้ส่งไม่ต้องรอเวลาเลย
อาจกล่าวได้ว่าความจุศูนย์เป็นระบบที่ไม่มีบัฟเฟอร์ก็ได้ ส่วนกรณีอื่นมีการจัดบัฟเฟอร์ให้อัตโนมัติ สำหรับในกรณีที่ไม่ใช่ศูนย์โปรเซสจะไม่รู้เลยว่าแมสเสจถึงปลายทางหรือไม่หลังจากการส่งเสร็จสิ้นไปแล้ว ถ้าข้อมูลนี้มีความสำคัญในการคำนวณ ผู้ส่งจะต้องติดต่อกับผู้รับเพื่อหาแมสเสจที่ส่งมาครั้งหลังสุด ตัวอย่างเช่น ถ้าโปรเซส P ส่งแมสเสจไปยังโปรเซส Q และสามารถเอ็กซิคิวต์ได้ต่อไปเฉพาะหลังจากที่แมสเสจได้รับไปแล้ว โปรเซส P จะมีขั้นตอนดังนี้


send( Q, message);
receive( Q, message);

โปรเซส Q จะเอ็กซิคิวต์คำสั่ง
receive ( P, message);
send ( P, “acknowledgment”);

การรับ-ส่งแมสเสจระหว่างโปรเซส P และโปรเซส Q ในลักษณะนี้เรียกว่า “asynchronous” อย่างไรก็ตามยังมี 2-3 กรณีที่ไม่เข้ากลุ่มใดตามที่กล่าวมาแล้วนี้
- การส่งแมสเสจของโปรเซสได้โดนไม่ต้องคอย กรณีนี้ถ้าผู้รับยังได้รับแมสเสจก่อนที่ผู้ส่งจะส่งแมสเสจอื่น แมสเสจแรกจะหายไป ข้อได้เปรียบของกรณีนี้ก็คือแมสเสจขนาดใหญ่ไม่จำเป็นต้องก็อปปี้ไว้หลายครั้ง ส่วนข้อเสียเปรียบคือการเขียนโปรแกรมของงานจะมีความยุ่งยาก โปรเซสเหล่านี้จำเป็นต้องมีการซินโครไนซ์แบบพิเศษเพื่อให้มั่นใจว่าแมสเสจไม่สูญหายไปไหน ทั้งผู้รับและผู้ส่งไม่ต้องคำนวรบัฟเฟอร์ของแมสเสจ
- การส่งแมสเสจของโปรเซสจะล่าช้าออกไปจนกว่าโปรเซสจะได้รับคำตอบ วีการี้นำมาใช้ในระบบปฏิบัติการที่ชื่อว่า Thoth โดยในระบบนี้แมสเสจจะมีขนาดแน่นอน (8 word) โปรเสซ P ที่แมสเสจจะถูกบล็อกจนกว่า โปรเซสี่ทำหน้าที่รับแมสเสจแล้วส่งคำตอบกับมา 8 word ในรูปแบบคำสั่ง reply(P,message) แมสเสจที่ตอบมานี้จะเขียนทับบัฟเฟอร์ดั้งเดิมของแมสเสจ ข้อแตกต่างระหว่าง send คือ คำสั่ง send จะทำให้โปรเซสที่ส่งแมสเสจเกิดการบล็อก ในขณะที่ reply จะยอมให้ทั้งโปรเซสที่ส่งแมสเสจและโปรเซสที่รับแมสเสจเอ็กซิติวต์ต่อไปได้เลยโดยไม่มีการบล็อก
2.6.4 เงื่อนไขยกเว้น
ระบบแมสเสจมีประโยชน์มนสภาพแวดล้อมแบบกระจายซึ่งโปรเซสอาจจะอยู่บนเครื่องอื่น ในสภาพ
แวดล้อมที่กล่าวถึงความน่าจะเป็นที่จะเกิดข้อผิดพลาดระหว่างการติดต่อสื่อสารและโปรเซสจะมากกว่าในสภาพ
แวดล้อมที่เป็นเครื่องเดียว สำหรับสภาพแวดล้อมที่เป็นเครื่องเดียว แมสเสจจะอยู่ในหน่วยความจำที่แชร์ ถ้าเกิดข้อผิดพลาดขึ้น ระบบโดยรวมจะล่ม แต่สำหรับในระบบกระจายแมสเสจจะถ่ายโอนไปตามสาย การเกิดข้อผิดพลาดที่เครื่องใดเครื่องหนึ่งไม่จำเป็นที่ระบบโดยรวมจะล่มก็ได้ ทั้งระบบที่เป็นศูนย์กลางคือระบบกระจายข้อผิดพลาดอาจจะได้รับการแก้ไข ตอนนี้เรามาพิจารณาเงื่อนไขยกเว้นที่ระบบต้องดูแลแมสเสจ
2.6.4.1 การสิ้นสุดของโปรเซส
ถ้าผู้รับหรือผู้ส่งแมสเสจสิ้นสุดก่อนแมสเสจจะเอกซิคิวต์ ในสภาวะแบบนี้ทำให้แมสเสจจะถูกกำจัด ทำให้ผู้รับไม่ได้รับแมสเสจ หรือผู้ส่งไม่ได้ส่งแมสเสจ ลองพิจารรา 2 กรณี ดังนี้
1. ผู้รับโปรเซส P อาจจะรอแมสเสจจากโปรเซส Q ที่สิ้นสุดไปแล้ว ถ้าไม่มีแอ็กชันใดๆ เกิดขึ้นโปรเซส P จะถูกบล็อกตลอดไป ในกรณีนี้ระบบอาจจะสั่งให้ P สิ้นสุด หรืออาจจะแจ้งให้ R ทราบว่า Q สิ้นสุดไปแล้วก็ได้
2. โปรเซส P อาจจะส่งแมสเสจไปยังโปรเซส Q ที่สิ้นสุดไปแล้ว รูปแบบการจัดบัฟเฟอร์แบบอัตโนมัติจะไม่เกิดอันตรายใดๆ โดย P ยังคงเอ็กซิคิวต์ต่อไป ถ้าโปรเซส P ต้องการทราบว่าแมสเสจของตนนั้นโปรเซส Q เอ็กซิคิวต์หรือไม่ จะต้องมีการโปรแกรมพิเศษสำหรับการแจ้งให้ทราบ แต่ในกรณีที่ไม่มีบัฟเฟอร์ โปรเซส P จะถูกบล็อกตลอดไปเช่นเดียวกับข้อ 1 ระบบอาจจะสั่งให้ P สิ้นสุด หรืออาจจะแจ้งให้ P ทายว่า Q สิ้นสุดไปแล้วก็ได้
2.6.4.2 การสูญหายของแมสเสจ
แมสเสจจากโปรเซส P ที่ส่งไปยังโปรเซส Q อาจจะสูญหายระหว่างทางของการสื่อสารก็ได้ ซึ่งอาจจะเป็นข้อผิดพลาดด้านฮาร์ดแวร์หรือสายสื่อสาร มี 3 วิธีพื้นฐานในการจัดการเหตุการณ์นี้
1. ระบบปฏิบัติการมีหน้าที่รับผิดชอบในการตรวจสอบการสูญหายนี้เพื่อส่งแมสเสจไปใหม่
2. โปรเซสที่ทำหน้าที่ส่งแมสเสจมีหน้าที่รับผิดชอบในการตรวจสอบการสูญหายเพื่อส่งแมสเสจใหม่ถ้าต้องการอีก
3. ระบบปฏิบัติการมีหน้าที่รับผิดชอบในการตรวจสอบการสูญหายนี้ หลังจากนั้นจะแจ้งให้โปรเซสที่ทำหน้าที่ส่งแมสเสจที่เกิดการสูญหายเพื่อให้ส่งแมสเสจไปใหม่

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

2.7 การซินโครไนซ์โปรเซส (Process Synchronization)
โดยปกติโปรเซสส่วนใหญ่ในระบจะไม่มีความเกี่ยวข้องกัน ต่างคนต่างเอ้กซิคิวต์ ลักษณะความเป็นอิสระนี้เรียกว่า “อะวิงโครนัส” (Asynchronous) แต่มีบางดปรเซสีมีความสัมพันธ์กัน นอกจากการติดต่อสื่อสารระหว่างโปรเซส (InterProcess Communication) ที่กล่าวไปแล้ว ยังมีการเข้าจังหวะของโปรเซสอีกด้วย การเข้าจังหวะของโปรเซสหรืออาจจะเรียกว่าโปรเซสนั้นเกิดการซินโครไนซ์กัน (Synchronize) การซินโครไนซ์โปรเซสจะหมายถึงการทำงานของโปรเซส 2 โปรเซสที่ต้องการมีความเกี่ยวข้องกัน อาจจะเป็นเพราะใช้รีซอร์สร่วมกัน หรืออาจจะเป็นการรอการเอ็กซิคิวต์โปรเซสหลังจากที่โปรเซสอื่นเอ็กซิคิวต์ไปแล้ว เป็นต้น ทำให้ต้องมีการรอจังหวะที่เหมาะสมเพื่อให้การทำงานนั้นถูกต้อง เพื่อความเข้าใจยิ่งขึ้นลองพิจารณารูป 2.12 จะเห็นว่าโปรเซส B จะเริ่มเอ็กซิคิวต์ได้ก็ต่อเมื่อโปรเซส A เอ็ดซิคิวต์เสร็จเรียบร้อยไปแล้ว (ซึ่งต่างกับโปรเซส C ที่ไม่ต้องรอโปรเซสใดเลยก้สามารถเอ็ก
ซิคิวต์ได้ทันที และไม่มีความเกี่ยวข้องกับโปรเซส A และ B เลย) ในทำนองเดียวกัน โปรเซส D จะเริ่มเอ็กซิคิวต์ได้ก็ต่อเมื่อมีการเอ็กซิคิวต์โปรเซส C และ C เสร็จเรียบร้อยไปแล้วนั่นเอง
ในการใช้รัซอร์สร่วมกันของดปรเซส 2 โปรเซสขึ้นไป อาจก่อให้เกิดปัญหาในการทำงานที่ถูกต้องสมมุติดปรเซสทั้งสองเป็นอิสระต่อกัน ทำงานในเวลาพร้อมๆ กัน และใช้ข้อมูลเดียวกันคือตัวแปร X ซึ่งกำหนดค่าเริ่มต้นไว้ที่ 10 โดยที่ โปรเซส A จะเป็นการเพิ่มค่าเข้าไปอีก 10 (X = X+10) ส่วนโปรเซส B จะเป็นการลดค่าจากเดิมออกไป 10(X = X-10)


จากรูป 2.13 โปรเซส A ทำงานก่อนโปรเซส B โดยอ่านค่า X เข้ามาซึ่งมีค่าเป็น 10 แล้วเพิ่มเข้าไปอีก 10 ทำให้ X มีค่าเป็น 20 แล้วเขียนลงหน่วยความจำ หลังจากนั้นโปรเซส B จึงอ่านค่า X เข้ามาซึ่งมีค่าเป็น 20 แล้วลบค่าออกไป 10 ทำให้ X มีค่าเป็น X ลงหน่วยความจำ

จากรูป 2.14 การทำงานจะคล้ายกับรูป 2.13 และได้ผลลัพธ์เหมือนกัน แต่โปรเซส B ทำงานก่อนโปรเซส A โดยอ่านค่า X เข้ามาซึ่งมีค่าเป็น 10 แล้วลบค่าออกไป 10 ทำให้ X มีค่าเป็น 0 แล้วเขียนลงหน่วยความจำ หลังจากนั้นโปรเซส A จึงอ่านค่า X เข้ามาซึ่งมีค่าเป็น 0 แล้วเพิ่มค่าเข้าไป 10 ทำให้ X มีค่าเป็น 10 แล้วเขียนค่า X ลงหน่วยความจำ สำหรับรูป 2.15 ทั้งโปรเซส A และ B จะทำงานพร้อมๆ กัน โดยค่าเริ่มต้น X เป็น 10 ทั้งสองโปรเซสจะได้ผลลัพธ์ที่ต่างกัน โดยโปรเซส A จะได้ค่า X เป็น 20 (จาก 10 เพิ่มอีก 10) ส่วนโปรเซส B จะได้ค่า X เป็น 0 (จาก 10 ลบออกไป 10) ถ้าโปรเซส A ทำงานเสร็จก่อนจะเขียนค่า X ซึ่งเท่ากับ 20 ลงหน่วยความจำ แต่ถ้าโปรเซส B ทำงานเสร็จก่อนจะเขียนค่า X ซึ่งเท่ากับ 0 ลงหน่วยความจำ ซึ่งทำให้เกิดข้อผิดพลาดเนื่องจากค่า X แน่นอน ขึ้นอยู่กับว่าโปรเซสใดทำงานเสร็จก่อน

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

2.8.1 Race Condition
ในบางระบบปฏิบัติการ โปรเซสที่ทำงานร่วมกันอาจจะมีการแชร์รีซอร์ส เช่น หน่วยความจำ หรือสื่อจัดเก็บข้อมูล หรือแชร์ไฟล์ซึ่งโปรเซสทั้งสองสามารถอ่านหรือเขียนรีซอร์สเหล่านี้ได้พร้อมกัน ทำให้ผลลัพธ์อาจจะเกิดการผิดพลาดขึ้นได้ขึ้นอยู่ว่าโปรเซสใดเข้ามาใช้ก่อน สภาวะที่เกิดขึ้นนี้เรียกว่า “Race Condition” เช่นเดียวกับการทำงานของโปรเซส A และโปรเซส B ในรูป 2.15 ที่ผ่านมา

2.8.2 Mutual Exclusion และ Critical Region
แล้วเราจะแก้สภาวะ Race Condition ได้อย่างไร คำตอบก็คือเราจะต้องหยุดไม่ได้เกิดการเอ็กซิคิวต์โปรเซสที่สอง ในขณะที่เอ็กซิคิวต์โปรเซสแรกอยู่ ถ้ายังมีโปรเซสแรกครอบครองรีซอร์สที่แชรืนั้นอยู่ โดยจะต้องรอจนกว่าโปรเซสแรกทำงานเสร็จเรียบร้อยก่อนเพื่อป้องกันไม่ให้เกิดข้อผิดพลาด วิธีการป้องกันไม่ให้โปรเซสอื่นเข้าไปใช้รีซอร์สในขณะที่โปรเซสใดๆ ครอบครองรีซอร์สอยู่นั้นเรียกว่า “Mutual Exclusion” หรืออาจจะเรียกว่า “การกีดกัน” โดยในบริเวณหรือส่วนของโปรแกรมที่โปรเซสเข้าไปครอบครองรีซอร์สนี้เรียกว่า Critical region หรือ Critical Section อาจกล่าวได้ว่าในสภาวะ Mutual Exclusion ถ้ามีโปรเซสใดก็ตามอยู่ใน Critical Region แล้ว โปรเซสอื่นจะเข้าไปอยู่ใน Critical Region ไม่ได้ ต้องรอให้โปรเซสนั้นออกมาจาก Critical Region ก่อน คุณสมบัติ 4 ประการของ Mutual Exclusion มีดังนี้
1. จะต้องไม่มีโปรเซส 2 โปรเซสอยู่ใน Critical Region พร้อมกัน
2. จะต้องไม่มีสมมุติฐานและข้อจำกัดเกี่ยวกับความเร็ว และจำนวนซีพียูมาเกี่ยวข้อง
3. จะต้องไม่มีโปรเซสใดๆ ภายนอก Critical Region ที่บล็อกการทำงานของโปรเซสอื่น
4. จะต้องไม่มีโปรเซสใดที่รอการเข้า Critical Region ตลอดเวลา

พิจารณา 2.16 เมื่อโปรเซส A เข้า Critical Region ที่เวลา T1 หลังจากนั้นเวลาผ่านไปเล็กน้อย ที่เวลา T2 โปรเซส B พยายามที่จะเข้า Critical Region แต่เข้าไม่ได้เนื่องจากมีโปรเซส A อยู่ใน Critical Region อยู่แล้ว (เราอนุญาตให้มีเพียงโปรเซสเดียวที่สามารถอยู่ใน Critical Region ได้) ทำให้โปรเซส B ถูกบล็อกไม่สามารถเข้า Critical Region ได้ จนกระทั่งที่เวลา T3 เมื่อโปรเซส A ออกจาก Critical Region แล้ว โปรเซส B จะเข้า Critical Region ได้ทันที จนกระทั่งที่เวลา T4 เมื่อโปรเซส B ออกจาก Critical Region แล้วก็จะกลับสู่สภาวะปกติที่ไม่มีโปรเซสใดอยู่ใน Critical Region เลย

2.8.3 Mutual Exclusion with busy waiting
เนื่องจากในสภาวะ Mutual Exclusion จะยอมให้มีการครอบครองรีซอร์สได้ครั้งละ 1 โปรเซสเท่านั้น ทำให้โปรเซสอื่นต้องรออยู่ภายนอก Critical Region แต่การรอของโปรเซสก็ยังเป็นการครอบครองเวลาซีพียูอยู่ ทำให้เสียประโยชน์เนื่องจากไม่ได้งานอะไรเลย การรอของโปรเซสในลักษณะนี้เรียกว่า Busy waiting เราจะต้องทำอะไรสักอย่างเพื่อขัดจังหวะการทำงานของซีพียู หรือกำหนดการทำงานของซีพียูเพื่อแก้ปัญหา busy waiting สำหรับารขัดจังหวะหรือที่เรียกว่า “อินเทอร์รัพต์” (Interrupt) นี้แบ่งเป็น 2 ประเภทคือ
- Clock Interrupt เป็นอินเทอร์รัพต์ที่บอกซีพียูว่าอยู่ในสภานะบล็อกรันครบเวลาควันตัม (Quantum time) แล้ว
- I/O Interrupt เป็นอินเทอร์รัพต์ที่บอกซีพียูว่าโปรเซสที่อยู่ในสภานะบล็อกนั้นทำงานกับอุปกรณ์อินพุต/เอาต์พุตเสร็จเรียบร้อยแล้ว และเมื่อซีพียูได้รับอินเทอร์รัพต์นี้แล้ว ซีพียูจะหยุดทำงานให้กับโปรเซสที่กำลังรันนั้นก่อน แล้วมาจัดการกับโปรเซสในสภานะบล็อกที่ส่งอินเทอร์รัพท์ไปเพื่อให้โปรเซสนั้นเสร็จงานและจะได้เปลี่ยนสภานะเป็นสภานะพร้อมได้
การแก้ปัญหา Mutual Exclusion with busy waiting มี 5 วิธีดังนี้
- Disable Interrupt
- Lock Variable
- Strict Alternation
- Peterson’s Slution
- TSL Instruction

2.8.3.1 Disable Interrupt
วิธีการนี้เป็นการยกเลิกอินเทอร์รัพต์ ทำให้ซีพียูทำงานได้อย่างต่อเนื่องโดยไม่สนใจอินเทอร์รัพต์ใดๆ เลย ทำให้โปรเซสที่อยู่ใน Critical Region ได้เอ็กซิคิวต์จนเสร็จเรียบร้อยจะได้ไม่เกิด Race Condition ขึ้นมาได้แต่หลังจากออกจาก Critical Region ไปแล้ว ซีพียูจึงจะสนใจอินเทอร์รัพต์ที่ส่งเข้ามา วิธีการยกเลิกอินเทอร์รัพต์ก็คือจะมีคำสั่ง Disable Interrupt ไว้ก่อนเข้า Critical Region ในทุกๆ โปรเซสที่มี Critical Region และจะต้องใช้คำสั่ง Able Interrupt ไว้ตอนท้ายสุดก่อนออกจาก Critical Region ดังรูป 2.17



รูป 2.17 Disable Interrupt ของโปรเซส A และโปรเซส B

ข้อเสียของวิธี Disable Interrupt มี 3 ประการคือ
- ถ้าใช้คำสั่ง Disable Interrupt ไว้ตอนต้นแต่ลืมใช้คำสั่ง Able Interrupt ไว้ท้ายสุดในโปรเซสของผู้ใช้ (User Process) หรือแอปพลิเคชันเพราะจะทำให้โปรเซสนั้นรันรวดเดียวจนจบ
- ไม่นิยมใช้ใน User Mode (Application Program) แต่นิยมใช้ใน Kernel Mode (System Program)
- คำสั่ง Disable Interrupt จะมีผลกับระบบที่ใช้ซีพียูเพียงตัวเดียว ในกรณีที่ระบบเป็นแบบหลายซีพียูจะใช้ไม่ได้ผล

นอกจากMonitor จะช่วยจัดการรีซอร์สที่จะต้องจะช่วยร่วมกันแล้ว Monitor ยังจะช่วยจัดการโปรเซสที่จะเข้าCritical regionเพื่อเข้าใช้ข้อมูลโดยผู้ใช้ทราบแต่เพียงว่ามีข้อมูลเหล่านั้นอยู่และทราบเพียงว่าจะใช้ข้อมูลนั้นในลักษณะใดบ้างเท่านั้น ไม่จำเป็นต้องทราบวิธีการเข้าไปใช้ข้อมูล ประโยชน์ของ Monitor ที่เห็นใด้ชัดเจนอีกอย่างหนึ่งคืการลดโอกาศที่จะเกิดข้อผิดพลาดจากโปรแกรมเมอร์ในส่ว่นที่เกี่ยวข้องกับ Mutural Exclusion เช่นเกิด Deadlock เป็นต้นทั้งนี้เนี่องจากส่วนที่เกี่ยวข้องดังกล่าวตัวแปลภาษา และคอมไพเลอร์จะสร้างให้โดยอัตโนมัติ ด้านล่างนี้เป็นโค๊ดเพี่อจินตนาการเกี่ยวกับMonitor


2.9 ปัญหาการทำงานของโปรเซส
ปัญหาที่เกิดขึ้นกับระบบปฎิบัติการเป็นปัญหาที่น่าสนใจและถกเถียงกันอย่างกว้างขวาง ตลอดจนมีการวิเคราะห์โดยการใช้วิธีการด้านซนโครไนซ์ ในที่นี้จะนำมากล่าว 3 ปัญหาดังนี้
2.9.1 The Dining Philosophers Problem
ปัยหาแรกนี้ไดจก์สตรา (ปี 1965) ได้เสนอไว้ โดยสมมุตว่ามีนักปราชญ์ 5 ท่านนั่งรอบโต๊ะกลมเพื่อทานอาหารที่วางตรงหน้า ในการทานอาหาร นักปราชญ์แต่ละท่านต้องใช้ตะเกียบทั้ง 2 ข้างที่วางที่วางอยู่ซ้ายมือและขวามือของนักปราชญ์ท่านนั้น เมื่อทานเสร็จในรอบนั้นจะต้องวางตะเกียบลงเพื่อเปิดโอกาสให้นักปราชญ์ท่านอื่นใด้ทานอาหารบ้าง จะเกิด Deadlock เมื่อนักปราชญ์ทั้ง 5 ท่านหยิบตะเกียบคนละ 1 ข้างพร้อมกัน สมมุตว่าทุกท่านหยิบตะเกียบข้างซ้ายมือพร้อมกัน ทุกท่านจะรอตะเกียบทางขวาว่างจึงจะทานอาหารใด้ และถ้ามีการสลับกันทานอาหารโดยนักปราชญืที่โชคร้ายถูกนักปราชญ์ซ้าย – ขวาสลับกันทานอาหาร ทำให้นักปราชญืท่านกลางม่มีโอกาสทานอาหาร เรียกปรากฎการเช่นนี้ว่า “ Starvation” ตัวอย่างโค๊ดข้างล่างนี้จะไม่ทำให้เกิด Deadlock และ
Starvation เพื่อป้งกันให้นักปราชญ์ทั้ง 5 ท่านเรียก thank ซึ่งเป็น binary Semaphorre ก่อนเริ่มหยิบ
ตะเกียบนักปราชญ์จะใช้ปฎิบัติการ Down ของ Mutex หลังจากเปลี่ยนตะเกียบจะใช้ปฎิบัตการ Up ของMutex ตามทฤษฎีน่าจะเพียงพอ แต่มีข้อจำกัดตรงที่จะมีนักปราชญ์เพียงท่านเดียวที่ทานอาหารในเวลาหนึ่งๆ เราจะไม่อณุญาตให้นักปราชญ์ 2 ท่านทานอาหารพร้อมกัน



รูป 2.18 โต๊ะอาหารการแก้ปัญหา Dinner Philosophers Problem ( Mos:p125)
#Define N 5 /* จำนวนนักปราชญ*/
Void philosopher(int i) /* Iแทนจำนวนนักปราชญ์ จาก0ถึง4*/

{
while ( TURE ) {
think(); /* นักปราชญ์คิด*/
take_chop(i); /* หยิบตะเกียบซ้าย */
take_chop (i+1)%N) /*หยิบตะเกียบขวา ; % คือโอเปอเรเตอร์
Modulo*/
eat( ); /* ทานอาหาร */
put_chop(i) /* วางตะเกียบซ้ายลงบนโต๊ะ */

put_chop(i+1)%N) ; /* วางตะเกียบซ้ายลงบนโต๊ะ */
ตัวอย่างข้างล่างนี้เป็นการแก้ปัญหาทำให้นักปราชญ์ทานอาหารใด้มากกว่า 1คน(สูงสุดเท่าที่จะยอมใด้ เช่นถ้ามีนักปราชญ์5คนก็จะทานใด้ 2 คนพร้อมกันใด้ จะใช้อาร์เรย์ที่ชื่อ state ติดตามสถานะว่านักปราชญ์ท่านใดกำลังกิน กำลังคิด หรือหิว (พยายามหยิบตะเกียบ) นักปราชญ์ 1 ท่าน อาจจะย้ายไปสถานะกำลังกินถ้าคนข้างใดกำลังกินข้างไม่ใช่สถานะกำลังกิน หมายเลขนักปราชญ์ข้างเคียงถูกกำหนดด้วยมาโครLIFEและRIGHTอาจกล่าวใด้ว่า ถ้าi คือ 2 แล้ว LIFTคือ1 และRIGHTคือ 3 ในโค้ดจะใช้อาเรย์ของ Semaphore 1 อาเรย์ต่อ 1 นักปราชญ์ ดังนั้นนักปราชญ์ที่หิวจะบล๊อกถ้าตะเกียบที่ต้องการใช้งานอยู่ จำใว้ว่าแต่ละโปรเซสรันโปรซีเดอร์ Philosopher
เป็นโค๊ดหลัก แต่โปรซีเดอร์อื่นทั้ง Take_chops,put_chopscและ test เป็นโปรดีเซอร์ธรรมดาและไม่ใด้แยกจากโปรเซส

#define N 5 /* จำนวนนักปราชญ์*/
#define LIFE (i+n-1)%N /* นักปราชญ์ที่อยู่ด้านซ้าย*/
#define RIGHT (i+n-1)%N /* นักปราชญ์ที่อยู่ด้านขวา*/
#define THINKING /* นักปราชญ์ที่กำลังคิด*/
#define HUNGRY /* นักปราชญ์ที่กำลังหยิบตะเกียบ*/
#define EATING 2 /* นักปราชญ์ที่กำลังกิน*/
Typedef int semaphore; /* Semaphore เป็นชนิดพิเศษของ int*/
int state[N]; /* อาร์เรย์เก็บสถานะของนักปราชญ์แต่ละคน*/
Semaphore mutex =1; /* Mutual ExclusionสำหรับCritical region*/
Semphore s[n]; /* 1 Semaphore ต่อ1 นักปราชญ์*/

Void philosopher(int i) /* i คือหมายเลขนักปราชญ์ จาก 0 ถึง N-1*/
{

while(true){ /*วนรอบ*/
think(); /* นักปราชญ์กำลังคิด*/
take_chops(i); /* ต้องการตะเกียบ 2 ข้างหรือบล๊อกใว้ก่อน*/
eat(); /* ทานอาหาร*/
put_chops(i); /* วางตะเกียบ 2 ข้างลงนโต๊ะ*/

}
}
void take_chops(int i) /* หมายเลขนักปราชญ์จาก 0 ถึง -1*/


{

Down( &mutex ) ; /* เข้า Critical region*/
state[i] = HUNGRY; /* บันทึกว่านักปราชญ์หิว*/
test(i); /* พยายามหยิบตะเกียบ*/
up(&mutex) /* ออกจาก critical region*/
down(&s[i]); /* บล๊กไว้ก่อนถ้าใด้ตะเกียบทั้ง 2 ข้าง */
}

Void put_chops(i) /* i คือหมายเลขนักปราชญ์ จาก 0 ถึง N-1*/
{

down( &mutex ); /* เข้า Critical region*/
statel[i]=thinking; /* นักปราชญ์ทานเสร็จแล้ว*/
test(LEFT); /* พิจรณาดูถ้าคนซ้ายทานใด้ตอนนี้*/
test(RIGHT) /* พิจรณาดูถ้าคนขวาทานใด้ตอนนี้*/
up(&mutex); /* ออกจาก Critical region*/
}

void test(i) /* หมายเลขนักปราชญ์จาก 0 ถึงN-1*/
{
if(state[I]==HUNGRY && state[LEFT]!=EATING && state[RIGHT]!=EATING){
state[I] = EATING;
up(&s[I];
}

}
2.9.2 The Readers – Writers Problem
ปัญหาการทานอาหารของนักปราชญ์มีประโยชน์มากสำหรับการเป็นโมเดลของโปรเซสที่ช่วยแก้ปัญหาการใช้รีซอร์สที่แชร์กันอยู่อย่างจำกัด ยังมีปัญหาอีกอย่างคือปัญหา Reader-Writer Problem (เสนอโดย Courtosisปี 1971) เป็นปัญหาเกี่ยวข้องกับระบบคอมพิวเตอร์ที่มีกลุ่มข้อมูลที่ใช้งานร่วมกัน ซึ่งมีโปรเซสอยู่ 2 ประเภท คือโปรเซสที่อ่านข้อมูลร่วม และโปรเซสที่บันทึกหรือเขียนข้อมูล ตัวอย่างเช่นระบบสำรองที่นั่งโดยสารเครื่องบิน ที่อาจจะมีเทอร์มินัลหลายพันหลายหมื่นตัวเพื่อสำรองที่นั่งในฐานข้อมูลเดียวกัน จะเห็นว่าในระบบมีผู้อ่าน (Reader)เป็นจำนวนมากเพื่ออ่านข้อมูล ในขณะเดียวกันก็อาจจะมีผู้เขียน (writer)ได้หลายคนเช่นกันเพื่อเขียนหรือบันทึกข้อมูล หลักการหรือปัญหานี้ก็คือมีผู้อ่านหลายคน (หลายโปรเซส) สามารถเข้าอ่านข้อมูลร่วมกันได้ไม่จำกัดจำนวน แต่สำหรับโปรเซสการเขียนข้อมูลไม่อาจใช้งานร่วมกันโปรเซสอื่นได้ไม่ว่าจะเป็นการอ่าน หรือเขียนข้อมูลการใช้ Monitor หรือการซินโครไนซ์อื่นๆ ไม่สามารถจัดการ Mutual Exclusion ได้ เนื่องจากต้องคำนึงถึงการรอคอยอีกด้วย เพราะผู้อ่านสามารถอ่านข้อมูลได้ตลอดเวลา ซึ่งถ้าผู้อ่านเข้ามาเรื่อยๆ ผู้เขียนก็ไม่สามารถเขียนข้อมูลได้เลยต้องรอไปเรื่อยๆจนกว่าผู้จะไม่มีผู้อ่านเข้ามา ในทำนองตรงข้าม ถ้าให้สิทธิของผู้เขียนมีมากกว่าผู้อ่าน ผู้อ่านก็จะถูกกีดกันไม่ให้ใช้ข้อมูลได้
การแก้ปัญหานี้(ตามโค้ดด้านล่าง)ผู้อ่านคนแรกที่เข้าทาใช้ฐานข้อมูลจะทำปฎิบัตการ Down ในSemaphore db ในขณะเดียวกันจะเพิ่มค่าตัวนับ arc ด้วย ในขณะที่ออกจากฐานข้อมูลจะลดค่าตัวนับ และคนสุดที่ออกไปจะทำปฎิบัติการ up ของ Semphore นอกจากนี้ยังบล็อกไม่ให้ผู้เขียนเข้ามาอีกด้วย แต่ถ้ามีผู้อ่านอยู่ก่อนแล้ว มีผู้อ่านคนต่อไปเข้ามาใหม่ก็สามารถใช้ฐานข้อมูลได้ รวมถึงผู้อ่านรายต่อๆไปด้วย สำหรับผู้เขียน
ถ้าเข้ามาต้องรอต่อไปจนกว่าจะไม่มีผู้อ่านเข้ามา สมมุติผู้อ่านจะเข้ามาทุก 3 วินาที และใช้เวลา 5 วินาทีในการอ่าน
ข้อมูล จากตัวเลขทั้งสองจะทำให้ผู้เขียนไม่สามารถเขียนข้อมูลได้เลย การแก้ปัญหาจะต้องกำหนดเพิ่มเติมเล็กน้อย
กล่าวคือถ้ามีผู้เขียนอยู่ก่อนแล้ว มีผู้อ่านเข้ามาใหม่ ผู้อ่านที่เข้ามาใหม่นั้นจะต้อไปรอคิวต่อจากผู้เขียน ถือหลัก
ที่ว่าใครมาหลังจะต้องต่อคิวเรื่อยไป จะทำให้แก้ปัญหาทั้ง 2 ทาง (ไม่ให้ผู้อ่านหรือผู้เขียนรอนานเกินไป)
Typeset into semaphore;
Semaphore mute = 1 /* ควบคุมการใช้ arc*/
Semaphore db = 1 /* ควบคุมการใช้ฐานข้อมูล*/
Int rc = 0; /* จำนวนโปรเซสที่อ่านหรือเขียน*/


Void reader (void)
{

white ( TURE ) { /*วนรอบ*/
down(&mutex); /* รับสิทธิ์การใช้ rc*/
rc = rc + 1; /* มีผู้เขียนเพิ่มขึ้นอีก 1 คน*/
if(rc = = 1)down (&db); /* ตรวจสอบว่าเป็นผู้อ่านคนแรกหรือไม่*/
up(&mutex); /* ปล่อยสิทธิ์การใช้ rc*/
read_data_base(); /* อ่านข้อมูล rc*/
down(&mutex); /* รับสิทธิ์การใช้ rc*/
rc = rc + 1; /* มีผู้เขียนลด 1 คน*/
if(rc = = o)up (&db); /* ตรวจสอบว่าเป็นผู้อ่านคนสุดท้ายหรือไม่*/
up(&mutex); /* ปล่อยสิทธิ์การใช้ rc*/
read_data_read(); /* ใช้ข้อมูล(นอกเหนือ Critical region*/
}
}


void writer (void)
{
white ( TURE ) { /*วนรอบ*/
thank_up_data(); /* นอกเหนือ Critical region*/
down(&db) /* รับสิทธ์การใช้ฐานข้อมูล*/
white_data_base(); /* เขียนข้อมูล rc*/
down(&mutex); /* รับสิทธิ์การใช้ rc*/
up(&db); /* ปล่อยสิทธิ์การใช้ฐานข้อมูล*/
}

}
2.9.3 The Sleeping Barber Problem
นอกจากปัญหาที่กล่าวมาแล้ว ทั้ง 2 ปัญหา ปัญหาที่ 3 เป็นปัญหาที่เกิดในร้านตัดผมที่มีช่างตัดผม 1 คนเก้าอี้ตัดผม 1 ตัว และมีเก้าอี้นั่งรอคิวจำนวนหนึ่ง ถ้าไม่มีลูกค้า ช่างตัดผมจะนอนพักผ่อนบนเก้าอี้ตัดผม เมื่อลูกค้าเข้ามาในร้านจะปลุกช่างตัดผมมาทำการตัดผม ถ้ามีลูกค้าเดินมาเข้าร้านเพิ่มอีก ก็จะนั่งรอ (ในกรณีที่มีเก้าอี้ว่าง) หรือไม่ก็ออกจากร้านไป (ในกรณีที่ไม่มีเก้าอี้ให้นั่งรอ) ปัญหาก็คือการ เขียนโปรแกรมเพื่อให้ช่างตัดผมและลูกค้าไม่เกิดการ Race Condition ปัญหานี้คล้ายกับการรอคิวเข้ารับบริการของโปรแกรมย่อยหรือโปรซีเดอร์ต่างๆที่เรียกเข้ามา
การแก้ปัญหาจะใช้ 3 Semaphone ดังนี้

เรายังต้องการตัวแปร waiting ที่ใช้นับจำนวนลูกค้าที่รอคิวตัดผม ซึ่งคือสำเนาของ Customer ที่เราจำเป็นต้องมีตัวแปร waiting ก็เนื่องจากเราไม่มีทางทราบจำนวน Semaphore ปจุบันเลย การแก้ปัญหานี้ก็คือลูกค้าที่เข้ามาในร้านจะนับจำนวนลูกค้าที่รอคิว ถ้าจำนวนน้อยกว่าจำนวนเก้าอี้ที่รอ ลูกค้าก็จะอยู่ในร้าน นอกนั้นจะออกจากร้านตัวอย่างโค๊ดด้านล่างนี้ แสดงถึงตอนเช้าช่างตัดผมเข้ามาในร้าน ก็เริ่มเอ็กซิคิวโปรซีเดอร์ barbersทำให้เขาถูกบล๊อกกับ Semaphore customer เนื่องจากค่าเริ่มต้นเป็น 0 (เนื่องจากยังไม่มีลูกค้า) ช่างตัดผมก็นอนรอลูกค้าจนกว่าจะมีลูกค้าคนแรกเข้ามา เมื่อลูกค้าเข้ามา ก็จะมีเอ็กซีคิวต์ customer เริ่มต้องการ Mutex เพื่อเข้าสู่ criticalregion ถ้ามีลูกค้าคนที่ 2 เข้ามาอีก คนนี้จะทำอะไรไม่ใด้จนกว่าลูกค้าคนแรกจะปล่อย Mutex โปรซีเดอร์ customer จะตรวจสอบจำนวนลูกค้าที่รอคิวว่ามีจำนวนน้อยกว่าเก้าอี้ที่ให้รอหรือไม่ ถ้าไม่ (ลูกค้าเกินจำนวนเก้าอี้)ก็จะปล่อยMutex แล้วก็ออกจากร้านไป แค่ถ้ามีเก้าอี้เหลือ โปรซีเดอร์ customer จะเพิ่มค่าตัวแปร waiting หลังจากนั้นจะทำ ปฎิบัติการ Up กับ Semaphore ดังนั้นจะปลุกให้ช่างตัดผมตื่น ตรงนี้เป็นจุดที่ช่างตัดผมและลูกค้าที่ตื่นอยู่ เมื่อลูกค้าปล่อย Mutex เริ่มตัดผม จนเมื่อการตัดผมเสร็จสิ้นลูกค้าออกจากโปรซีเดอร์ และออกจากร้าน จะเห็นว่าโค้ดจะต่างจากตัวอย่างที่ผ่านมาที่ไม่มีการรวนรอบ เนื่องจากลูกค้า 1 คนจะตัดผมเพียงครั้งเดียว แต่ช่างตัดผมจะวนรอบเพื่อให้บริการกับลูกค้าคนต่อไป (ถ้ามีลูกค้า) แต่ถ้าไม่มีก็จะนอนรอต่อไป
#define CHAIR 5 /*จำนวนเก้าอี้ให้ลูกค้ารอคิว*/
typedef int semaphore
semaphore customers = o; /* จำนวนลูกค้าที่คอยคิวบริการ*/
semaphore barbers = o; /* จำนวนช่างตัดผมที่รอลูกค้า*/
semaphore mutex = o; /* สำหรับMutual Exclusion*/
int waiting = 0 /* ลูกค้าที่คอยคิว (ยังไม่ใด้ตัด) */
void barber(viod
{

white ( TURE ) {

down(&customers); /* นอนรอ ถ้าจำนวนลูกค้าเป็น o*/
down(& mutex); /* รับสิทธ์การใช้waiting*/
waiting=waiting - 1 /*ลดค่าตัวนับจำนวนลูกค้าที่คอยคิว1ค่า*/
up( &barbers ); /* ช่าง 1 คนพร้อมที่จะตัดผมแล้ว*/
up( &mutex ); /* ปล่อยสิทธิ์waiting*/
cut_hair(); /* ตัดผม(นอก Critical region*/
}

{
Voild customer( voild )

{
down (& mutex ); /*เข้า Critical region*/
2.10 Thread
โปรเซสที่กล่าวผ่านมาเป็นการเอ็กซิคิวต์โปรแกรมในลักษณะมีการควบคุมเพียง 1 Thread (แต่ละโปรเซสจะประกอบด้วย Thread เพียง Thread เดียวเท่านั้น) แต่ในระบบการปฎิบัติการสมัยใหม่การสมัยใหม่ในแต่ละโปรเซสสามาถมีได้หลายThread อาจจะกล่าวใด้ว่า Thread ก็คือส่วนประกอบย่อยของโปรเซสนั่นเอง จนบางครั้งอาจเรียก Thread ว่า “LightWeight Process” ในรูป 2.19 (ก) คุณจะเห็นโปรเซส 3 โปรเซส แต่ละโปรเซสจะมีแอ็ดเรสเป็นของตนเอง และควบคุมเพียง 1 เท่านั้น แต่ละรูป 2.19 (ข) จะเห็นว่าในแต่ละโปรเซสจะควบคุม3 Thread โดยใช้แอ็ดแรสเดียวกันอยู่



รูป2.19 ( ก ) 3 โปรเซสแต่ละโปรเซสจะมี 1 Thread ( ข ) 1 โปรเซสที่มี 3 Thread [MOS:P82]
Thread เป็นหน่วยพื้นฐานของการจัดสรรการใช้ประโยชน์ของของซีพียู ที่ประกอบด้วย
ภายในโปรเซสจะประกอบด้วย Thread จะมีการแชร์โค้ด,ข้อมูล และรีซอร์ส เช่น ไฟล์, อุปกรณ์ต่างๆเป็นต้น โปรเซสดั้งเดิม (ที่เรียกว่า heavyweight ) ที่มีการควบคุมเพียง 1 Thread แสดงว่าทำงานใด้ 1 งาน แต่ถ้าโปรเซสมีหลาย Thread ( อาจเรียกว่า multithread ) จะทำงานใด้หลายงานในเวลาเดียวกัน รูป 2.20 แสดงส่วนประกอบของโปรเซส ที่เป็น single-thread และ multithread

รูป2.20 โปรเซสที่เป็น single-threaded และ Multithread [OSC6:P130]
ซอฟแวร์ปจุบันที่รันกับเครื่องพีซีสมัยใหม่มีการออกแบบให้เป็น multithread โดยแยกออกเป็น
โปรเซสที่ควบคุมหลายๆ thread เช่น โปรแกรมเวบบราวเซอร์ที่มี thread หนึ่งในการแสดงรูปภาพหรือเขียนข้อความใขขณะที่อีก thread หนึ่งกำลังดึงข้อมูลจากเน้ตเวิร์ค หรืออย่างในโปรแกรมเวิร์ดโปรเซสเซอร์ที่มีหลาย thread โดยที่thread หนึ่งกำลังแสดงภาพกราฟฟิก ในขณะที่ thread ที่สองกำลังรอรับคำสั่งจากคีย์บอร์ดจากผู้ใช้ ในขณะที่ threadที่สามกำลังตรวจสอบคำสะกดและไวยกรณ์ในลักษณะแบ็คกราวนด์ เป็นต้น
2.10.1 ข้อใด้เปรียบของ multithreaded
การที่ระบบปฎิบัติการสนับสนุนระบบ multithread ทำให้มีข้อใด้เปรียบ 4 กลุ่มหลัก ๆ ดังนี้
1.การตอบสนอง : ระบบ multithread ที่โต้ตอบแอปพลิเคชันจะยินยอมให้โปรแกรมยังคงดำเนินต่อไปถึงแม้ว่าจะมีบางส่วนถูกบล๊อกหรือมีการปฎิบัติที่ยาวนานเนื่องจากการเพิ่มการ โต้ตอบกับผู้ใช้นั่นเอง ยกตัวอย่างเช่น โปรแกรมเว็บบราวเซอร์ยังคงโต้ตอบกับผู้ใช้ได้ ในขณะที่มีหนึ่งที่กำลังโหลดรูปภาพอยู่
2.การแชร์รีซอร์ส : โดยปกติ thread จะแชร์หน่วยความจำ และรีซอร์สของโปรเซสอยู่แล้ว ข้อได้เปรียบ ของการแชร์โค้ดจะทำให้แอปพลิเคชันสามารถมีกิจกรรมของ thread ใด้หลายๆกิจกรรมภายในแอ็ดเดรสเดียวกัน
3.ความประหยัด : การจัดสรรหน่วยความจำและรีซอร์สสำหรับการสร้างโปรเซสมีค่าใช้จ่ายมาก ในทางตรงข้าม เนื่องจาก thread แชร์รีซอร์สของโปรเซสทีมันอาศัยอยู่แล้ว ทำให้เกิดการประหยัดในการสร้างthreadและทำการ context switch ของ threadเป็นการยากที่จะวัดความแตกต่างระหว่างการสร้างและคงสภาพโปรเซสที่มีมากกว่าthreadได้ แต่โดยปกติแล้วจะใช้เวลาในการสร้างและคงสภาพโปรเซสสูงกว่าเวลาที่ใช้กับ thread ใน Solaris2 การสร้างโปรเซสจะช้ากว่าการสร้าง thread 30 เท่าและcontext switch จะช้ากว่า 5 เท่า
4.การเอื้อประโยชน์ของสถาปัตยกรรมมัลติโปรเซสเซอร์ : ข้อใด้เปรียบของ multithread ช่วยเสริมสถาปัตกรรมมัลติโปรเซสเซอร์ให้สูงขึ้น ในขณะที่แต่ละ thread สามารถรันขนานกันไปใน
โปรเซสเซอร์อื่นใด้ในโปรเซสที่มี thread เดียวสามารถรันเพียงซีพียูเดียวเท่านั้น ไม่ว่าจะมีกี่ซีพียูก็ตามระบบ multithread ในเครื่องที่มีหลายซีพียูจะเพิ่มประสิทธิภาพในการทำงานพร้อม ๆ กันใด้มากขึ้น ในสถาปัตยกรรมที่มีซีพียูเดียว ซีพียูจะย้ายแต่ละ thread ให้เร็วมากขึ้นเพื่อให้ทำงานเสมือนว่าขนานกันอยู่ แต่ในความเป็นจริงจะรันเพียง thread เดียวเท่านั้นในเวลานั้น ๆ
2.10.2 User และ Kernel Thread
Thread อาจจะแบ่งตามการระดับการสนับสนุนใด้ 2 แบบคือ User Thread และ Kernel Thread ซึ่งเป็นแบบที่น่าสนใจ ดังนี้
• User Thread จะใด้รับการสนับสนุนจาก kernel ด้านบน และอยู่ในไลบรารีของ thread ในระดับของ ผู้ใช้ ไลบรารียังสนับสนุนการสร้าง thread การจัดเวลา และการจัดการ thread โดยไม่ต้องใด้รับการ สนับสนุนจาก kernel เนื่องจาก kernel ไม่ต้องยุ่งเกี่ยวกับ thread ระดับผู้ใช้ การสร้าง thread และ การจัดเวลา thread ทั้งหมดจะกระทำเสร็จสิ้นภายในพื้นที่ของผู้ใช้โดยไม่จำเป็นต้องใช้ kernel ดังนั้น thread ในระดับผู้นำผู้ใช้สามารถสร้างและจัดการใด้อย่างรวดเร็ว อย่างไรก็ตาม ถ้า kernel เป็น single-thread แล้ว thread ระดับผู้ใช้จะบล๊อก system call จนเป็นเหตุให้ทุกโปรเซสถูกบล๊อก ถึงแม้ว่า thread อื่น จะยังคงรันอยู่ในแอปพลิเคชั่นก็ตาม ไลบรารีของ User thread รวมถึง POSIX Pthreads, Mach C-threads และSolaris 2UI-threads
• Kernel thread ที่ได้รับการสนับสนุนโดยตรงจากระบบปฎิบัติการ kernel จะสร้าง จัดเวลา และการจัดการthread ภายในพื้นที่ของ kernel เอง เนื่องจากระบบปฎิบัติการเป็นผู้จัดการเกี่ยวกับการสร้าง และ จัดการ thread เอง จึงทำให้ kernel thread จะสร้างและจัดการใด้ช้ากว่า User thread อย่างไรก็ตาม เพราะ kernel จัดการเกี่ยวกับ thread ดังนั้นถ้า thread เกิดการบล๊อก system call จะทำให้ kernel จัดการนำเอา thread อื่นในแอปพลิเคชั่นเข้ามาเอ็กซิคิวต์แทนใด้ เช่นเดียวกับในสภาวะมัลติโปรเซสเซอร์ที่ kernel สามารถจัด thread ลงในโปรเซสเซอร์อื่นใด้ ระบบปฎิบัติการที่สนับสนุน kernel thread เช่น Window NT,Window XP, Window 2000, Solaris 2,BeOS,และTru64 UNIX


2.10.3 โมเดลของ Multithreading
มีหลายระบบที่สนับสนุนทั้ง User Thread และ Kernel Thread ในโทมเดลที่ต่างกัน เรามาพิจรณาในโมเดล ทั้งสามของ Threading ดังนี้

• โมเดล Many-to-One เป็นโมเดลที่ใช้ Kernel thread 1 หน่วย กับ User thread หลายหน่วย (ดังรูป 2.21) การจัดการ thread จะอยู่ในพื้นที่ของผู้ใช้ ซึ่งมีประสิทธิภาพ แต่ถ้า thread บล๊อก system call โปรเซสทั้งหมดจะถูกบล๊อกไปด้วย เนื่องจากจะมีเพียง thread เดียวเท่านั้นที่เอ็กเซส kernel ในเวลาหนึ่งๆ thread หลาย ๆ thread ไม่สามารถรันขนานกันในระบบมัลติโปรเซสเซอร์ร์ใด้ ระบบที่ใช้โมเดลนี้เช่น Green thread ซึ่งเป็นไลบรารีใน Solaris 2 นอกจากนี้ในไลบรารีของ User thread ในระบบ ปฎิบัติการที่ไม่สนับสนุน Kernel thread จะใช้โมเดล Many-to-One นี้



โมเดล One-to-One เป็นโมเดลที่แต่ละ User thread จะจับคู่กับ Kernel thread ในลักษณะ 1 ต่อ 1
(ดังรูป 2.22) ทำให้สามารถทำงานทำงานพร้อมกันดีกว่าแบบ Many-to-One โดยยอมให้ thread อื่นรันใด้เมื่อ thread บล๊อก system call นอกจากนี้โมเดลนี้ยังยอมให้รันหลาย ๆ thread แบบขนานกันในระบบมัลติดปรเวสเซอร์ใด้อีกด้วย มีข้อที่คำนึงอยู่ข้อเดียวคือ การสร้าง User thread จำเป็นต้องสร้าง Kernel thread ที่สัมพันธ์กันด้วย เนื่องจากการสร้าง Kernel thread เป็นส่วนสำคัญในประสิทธิภาพของแอปพลิเคชัน ระบบที่โมเดลมีข้อจำกัดที่จำนวน thread ที่สนับสนุนในระบบใด้ โมเดลนี้นำมาใช้ในนระบบ เช่น Window NT,Window XP, Window 2000,และ os/2



• โมเดล Many-to-Many เป็นโมเดลที่อาจจะมีจำนวน User thread มากกว่าหรือเท่ากับจำนวน Kernel thread ก็เป็นใด้ (ดังรูป2.33) จำนวน kernel thread อาจจะเป็นตัวกำหนดแอปพลิเคชันเฉพาะ หรือเครื่อง เฉพาะ (แอปพลิเคชันอาจจะมี kernel thread บนมัลติโปรเซสเซอร์มากกว่า kernel thread บนโปรเซสเซอร์เดียว) ในขณะที่โมเดล Many-to-Many ยอมให้ผู้พัฒนาสร้าง User thread ใด้ตามที่เขาต้องการ แต่จะไม่สามารถรันใด้พร้อมกัน เนื่องจาก kernel จะจัดเวลาให้ครั้งละ thread เท่านั้น โมเดลOne-to-One ยอมให้รันพร้อมกันใด้ดีกว่า แต่ผู้พัฒนาต้องระวังว่าต้องไม่สร้าง thread มากเกินไปใน แอปพลิเคชัน ( ในบางครั้งอาจจะจำกัดจำนวน thread ที่จะสร้าง) โมเดล Many-to-Many จะลดข้อจำกัดของโมเดลทั้งสอง กล่าวคือ ผู้พัฒนาสามารถสร้าง User thread เท่าที่จำเป็น และสัมพันธ์กับ Kernel thread ที่สามารถรันแบบขนานในระบบมัลติโปรเซสเซอร์ นอกจากนั้น เมื่อ thread เกิดการบล็อก system call แล้ว kernel จะจัดเวลาเพื่อนำ thread อื่นขึ้นมารันก่อนก็ใด้ โมเดลนี้เป้นตัวอย่างของ
ระบบ Solaris 2,IRIX,HP-UXและ Tru64 UNIX เป็นต้น
2.10.4 การยกเลิก thread
การยกเลิก thread เป็นการทำให้ thread จบการทำงานก่อนที่จะสมบูรณ์ เช่น ถ้ามี หลาย thread
ค้นหาข้อมูลในฐานข้อมูล พร้อมกัน แล้วมี thread หนึ่งให้ผลลัพท์ออกมาแล้ว thread ที่เหลือจะถูกยกเลิกในภาวะอื่นอาจจะเกิดเมื่อผู้ใช้กดปุ่มบนโปรแกรมเว็บบราวเซอร์เพื่อหยุดการดหลดข้อมูล เนื่องจากการโหลดข้อมูลจะใช้ thread แยกกับการกดปุ่มบนคีย์บอร์ด ดังนั้นเมื่อมีการกดปุ่ม Stop บนคีย์บอร์ดจึงทำให้โปรเกรมเว็บบราวเซอร์หยุดการโหลดข้อมูล นั่นเอง thread ที่ถูกยกเลิกอาจเรียกว่า target thread ซึ่งการยกเลิกอาจมี 2 รูปแบบที่ต่างกัน ดังนี้ความยุ่งยากในการยกเลิกจะเกิดในภาวะที่รีซอร์สถูกกำหนดให้ยกเลิก thread หรือมี thread หนึ่งถูกยกเลิกในขณะอยุ่ระหว่างการอัปเดทข้อมูลที่แชร์อยู่กับ thread อื่น สิ่งนี้เป็นกรณีพิเศษของการยกเลิกแบบ Asynchronous ระบบปฎิบัติการมักจะแก้ปัญหารีซอร์สจากการยกเลิก thread แต่ไม่ใช่ทุกรีซอร์ส ดังนั้นการยกเลิกแบบ Asynchronous อาจจะใช้กับรีซอร์สทั่วไปไม่ได้ ในทางกลับกัน การยกเลิกแบบ Deferred จะทำงานโดยมี thread หนึ่งที่กำหนดว่า target thread ใดจะถูกยกเลิก อย่างไรก็ตาม การยกเลิกนี้จะเกิดขึ้นเฉพาะเมื่อ target thread นั้นตรวจสอบว่าตัวเองจะถูกยกเลิกหรือไม่ สิงนี้ยอมให้ thread ตรวจสอบ เพื่อให้ถูกยกเลิกในจุดที่ปลอดภัยถ้ายกเลิก จุดที่ว่านี้ใน Pthread API เรียกว่าCancellation Points ในระบบปบัติการส่วนมากจะยอมให้โปรเซสหรือ thread ถูกยกเลิกแบบ Asynchronous แต่ใน Pthread API ยังสนับสนุนการยกเลิกแบบ Defferred อีกด้วย สิ่งนี้หมายวความว่าระบบปฎิบัติการที่มี PthreadAPI จะยอมให้ยกเลิกแบบ Defferred นั่นเอง
2.11 สรุป
การจัดการโปรเซสของระบบปฎิบัติการเป็นเรื่องที่สำคัญที่สุด เนื่องจากโปรเซสก็คือโปรแกรมที่กำลังเอ็กซิคิวต์ หรือก็คืองานที่ส่งเข้ามาให้ ซีพียูจัดเวลาเพื่อเข้าทำงานนั่นเอง ส่วนประกอบของโปรเซสจะมีหมายเลขโปรเซส,โค๊ดโปรแกรม,ข้อมูล,บล๊อกควบคุมโปรเซส,ตัวควบคุมลำดับการเอ็กซิคิวต์คำสั่งขอโปรเซส และคุณสมบัติของโปรเซส ในโปรเซสนั้นจะมีสถานะแสดงการทำงานของโปรเซสไว้ ซึ่งจะมีสถานะเริ่มต้น,พร้อมทำงานลรันลรอลบล๊อก และสถานะสิ้นสุด โปรเซสจะควบคุมการสร่งโปรเซสใหม่ผ่านทาง System Call ของระบบปฎิบัติการการทำงานของโปรเวสแม่และโปรเซสลูกจะสัมพันธ์กัน นอกจากนี้โปรเซสยังต้องทำงานร่วมกับโปรเซสอื่น ดังนั้นโปรเซสอาจจะมีผลกรทบ หรือใด้รับผลกระทบจากโปรเซสอื่น ก็ได้ การควบคุมให้โปรเซสสองโปรเซสทำงานร่วมกันใด้ทีเรียกว่า การซินโครไนซ์โปรเซสนั้น เป็นเรื่องที่ยุ่งยาก และเป็นหน้าที่ของระบบปฎิบัติการที่จะต้องจัดการ เช่น การแก้ปัญหาการแก้ปัญหาจากการที่โปรเซสเข้าไปใช้รีซอร์สใดพร้อมกันที่เรียกว่า Race Condition ระบบการปฎิบัติการจะต้องป้องกันเข้า Critical Region ให้ดีนั่นเอง.


(waiting<>

บทที่4วงจรอับ

วงจรอับ(Deadlock)
ระบบคอมพิวเตอร์โดยทั่วไปนั้นประกอบไปด้วยทรัพยากร หรือ รีซอร์ส (resource) จำนวนมากที่สามารถถูกเรียกใช้งานได้โดยโปรเซล(Process)หนึ่ง ณ เวลาขณะใดขณะหนึ่งเท่านั้น ตัวอย่างที่สามารถมองเห็นได้อย่างชัดเจน ได้แก่ เครื่องพิมพ์ (Printer), ฟลอบบี้ไดรฟ์ (floppy drive) หรือเทปสำรองข้อมูล (tape backup) เป็นต้น ทรัพยากรเหล่านี้จะไม่อนุญาตให้มีโปรเซลมากกว่า 1 โปรเซลเข้ามาใช้พร้อม ๆ กัน เช่น การที่โปรเซล 2 ตัวเข้ามาใช้ระบบไฟล์ เดียวกัน และทำการเขียนหรือเปลี่ยนแปลงระบบไฟล์นั้น พร้อม ๆ กัน อาจจะทำให้ไฟล์นั้นเกิดความเสียหาย หรือสูญเสียได้ ดังนั้นระบบปฏิบัติการที่ดีจะต้องมีความสามารถที่จะหยุดการทำงานของโปรเซลใดๆ เป็นการชั่วคราวได้ ถ้าโปรเซลนั้นพยายามเรียกใช้ทรัพยากรที่กำลังถูกใช้งานอยู่ และทำให้เกิดข้อผิดพลาดดังกล่าว
โปรแกรม หรือแอปพลิเคชันโดยทั่วไปเมื่อทำงาน จะเกิดโปรเซลขึ้นมากมาย และโปรเซลเหล่านี้ส่วนใหญ่ต้องการใช้ทรัพยากรมากกว่า 1 สมมุติว่าการทำงานของโปรแกรมหนึ่ง ทำให้เกิดโปรเซล A และ โปรเซล B เริ่มแรกโปรเซล A ร้องขอใช้เคริ่องสแกนเนอร์ (Scanner) และได้ใช้งาน ส่วนโปรเซล B ถูกโปรแกรมขึ้นมาเพื่อเรียกใช้เครื่องเขียนแผ่นซีดี (CD Writer) ก่อนและได้ใช้งาน ต่อมาโปรเซล A ต้องการใช้เครื่องเขียนแผ่นซืดีบ้าง จึงได้ร้องขอกับระบบ แต่ถูกปฏิเสธจนกว่าโปรเซล B ใช้งานเสร็จ และก็อาจจะเป็นความบังเอิญหรือความโชคร้ายของระบบปฏิบัติการที่โปรเซล B ได้รองขอสแกนเนอร์เพื่อใช้งานพร้อม ๆ กัน ณ จุดนี้เองที่โปรเซลทั้งสองจะถูกปฏิสธให้ทำงานและหยุดเพื่อรอทรัพยากรของอีกฝ่ายหนึ่งโดยไม่มีวันที่จะได้รับทรัพยากรของอีกฝ่ายเลย ดังในรูปที่ 4.1 ซึ่งเหตุการณ์นี้เองที่เรียกว่า วงจรอับ หรือ deadlock
วงจรอับไม่จำเป็นที่จะต้องเกิดขึ้นภายในเครื่องคอมพิวเตอร์เครื่องเดียวเท่านั้น วงจรอับสามารถเกิดข้ามเครื่องได้เช่นกัน เช่น ในระบบเครือข่ายของสำนักงาน (Network) บางครั้งอุปกรณ์ที่เชื่อมต่อกับระบบและสามารถเรียกใช้งานได้โดยผู้ใช้หลาย ๆ คน เช่น เครื่องพิมพ์ เป็นต้น โดยเหตุการณ์และวิธีการป้องกันการเกิดวงจรอับก็จะสลับซับซ้อนและยากขึ้นเป็นลำดับ เมื่อมีอุปกรณ์หรือผู้ใช้เข้าไปเกี่ยวข้องกับระบบมากขึ้น



รูปที่ 4.1 การเกิดวงจรอับโดยโปรเซสทั้งสองต่างก็รอใช้ทรัพยากรของอีกฝ่ายหนึ่ง

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

รถยนต์ที่วิ่งไปทิศเหนือจะต้องใช้เส้นทางที่ 1 และ 2
รถยนต์ที่วิ่งไปทิศตะวันตกจะต้องใช้เส้นทางที่ 2 และ 3
รถยนต์ที่วิ่งไปทิศใต้จะต้องใช้เส้นทางที่ 3 และ 4
รถยนต์ที่วิ่งไปทิศตะวันออกจะต้องใช้เส้นทางที่ 4 และ 1

รูปที่ 4.2 ตัวอย่างภาพแสดงการเกิดวงจรอับ (Deadlock) [OSID:P254]
โดยปกติเมื่อขับรถเข้าไปในสี่แยก เราจะอนุญาตให้รถที่วิ่งมาทางด้านขวามือไปก่อน ซึ่งกฎดังกล่าวสมารถใช้งานได้ในกรณีที่มีรถเข้ามาจำนวน 2 หรือ 3 ครัน เช่น ถ้ารถที่จะวิ่งไปทิศเหนือมาพร้อมกับรถที่จะวิ่งไปทิศตะวันตกพร้อมกัน รถที่วิ่งไปทิศเหนือจะต้องรอรถที่วิ่งไปทิศตะวันตกไปก่อน อย่างไรก็ตามถ้ารถยนต์ทั้งสี่คันเข้ามาพร้อมกัน แต่ละคันจะต้องรอรถฝั่งขวามือก่อน(ตามกฎที่ตั้งไว้) ซึ่งเป็นการรอในลักษณะวนรอบโดยไม่มีที่สิ้นสุด และก็เกิดวงจรอับขึ้น แต่ถ้ารถทั้งสี่คันไม่ปฎิบัติตามกฎดังกล่าวและแล่นเข้ามาในสี่แยก โดยที่รถแต่ละคันก็จองเส้นทางคนละ 1 เส้น(ดังในรูปที่ 4.2 (ข)) แต่รถทั้งสี่ยังไม่สามารถทำงานต่อไปได้เพราะว่าเส้นทางที่ต้องการอีก 1 เส้น ได้ถูกจองไว้แล้วโดยรถคันอื่น และเราก็เข้าสู่วงจรอับอีกครั้งหนึ่ง

4.2 เงื่อนไขที่ทำให้เกิดวงจรอับ
วงจรอับ เป็นสถานการณ์ที่เราไม่ต้องการให้เกิดขึ้นในระบบ เพราะว่าเมื่อเกิดวงจรอับขึ้นมา จะทำให้ไม่มีโปรเซสใดสามารถทำงานจนเสร็จสมบูรณ์ได้ และทรัพยากรของระบบจะถูกครอบครองจนหมด ดังนั้นก่อนที่เราจะกล่าวลึกลงในรายละเอียดเกี่ยวกับการจัดการกับวงจรอับนั้น เราควรเรียนรู้เกี่ยวกับสาเหตุสำคัญที่ทำให้เกิดวงจรอับก่อน
วงจรอับอาจจะเกิดขึ้นก็ต่อเมื่อเงื่อนไขทั้งสามข้อต่อไปนี้เกิดขึ้น
1. เมื่อมีทรัพยากรที่ไม่สามารถถูกใช้ร่วมกับหลาย ๆ โปรเซสพร้อมกันได้ (Mutual exclusion condition) ถ้ามีทรัพยากรอย่างน้อย 1 ตัวในระบบที่จะยอมให้โปรเซสเพียง 1 ตัว ใช้งานมันได้เท่านั้น นั่นก็คือ ถ้ามีโปรเซสอื่นเข้ามาร้องขอให้ช้งาน โปรเซสนั้นจะต้องรอจนกว่าโปรเซสดังกล่าวได้ใช้งานเสร็จและปล่อยทรัพยากรนั้นว่าง
2. เมื่อมีการถือครองและรอ(Hold and wait condition) ถ้าโปรเซสสามารถถือครองทรพัยากรที่ตัวเองได้รับ และในขณะเดียวกันก็สามารถทำการร้องขอทรัพยากรเพิ่มเติ่มได้
3. เมื่อการทำงานในระบบไม่มีการแทรกกลางคัน (No preemption condition) ถ้าโปรเซสกำลังใช้งานทรัพยากรอยู่ และระบบไม่สามารถบังคับให้โปรเซสนั้นปลดปล่อยทรัพยากรนั้นให้เป็นอิสระได้ โดยทรัพยากรจะเป็นอิสระได้ก็ต่อเมื่อโปรเซสยกเลิกการถือครองเท่านั้น
เงื่อนไขทั้งสามข้อด้านบนนั้นเป็นสิ่งที่ระบบปฎิบัติการทั่วไปต้องการและใช้อยู่ เพื่อให้ระบบ
ทำงานได้อย่างถูกต้อง ตัวอย่างเช่น การที่ทรัพยากรไม่สามารถถูกใช้ร่วมกับหลาย ๆ โปรเซสได้นั้น มีความจำเป็นสำหรับการใช้งานของฐานข้อมูลเพื่อให้เกิดความถูกต้องและตรงกัน เช่นเดียวกับการแทรกกลางคันของระบบนั้น ไม่ควรเกิดขึ้น ถ้าปราศจากเหตุผลอันควร โดยเฉพาะเมื่อระบบทำงานเกี่ยวข้องกับทรัพยากรที่เป็นข้อมูลที่เราต้องการให้ระบบแบ็คอัพข้อมูลเหล่านั้นได้ นั่นคือ ระบบสามารถเรียกโปรเซสและข้อมูลที่เหมาะสมมาใช้ได้อีกเมื่อเกิดการสูญหายของข้อมูล
อย่างไรก็ตาม เงื่อนไขทั้งสามอาจจะทำให้เกิด หรือ ไม่ทำให้เกิดวงจรอับก็ได้ วงจรอับจะ
เกิดขึ้นจริงก็ต่อเมื่อเงื่อนไขที่สีเกิดขึ้น
4. เมื่อเกิดวงจรรอคอย (Circuit wait condition) ถ้าเกิดวงจรลูกโซ่ของโปรเซส 2 ตัว หรือ มากกว่า
ที่ต่างรอคอยทรัพยากรที่ถือครองโดยโปรเซสที่อยู่ในวงจรลูกโซ่นั้น ดังในรูปที่ 4.3

รูปที่ 4.3 วงจรลูกโซ่ของโปรเซสที่ต่างรอคอยซึ่งกันและกัน [OSID:P260]

เงื่อนไขสามข้อแรกนั้นจำเป็น แต่ไม่เพียงพอต่อการทำให้เกิดวงจรอับ เงื่อนที่สี่แท้จริงแล้วเป็นผลที่เกิดจากเงื่อนไขทั้งสามข้อแรก นั่นคือ เมื่อเงื่อนไขทั้งสามข้อแรกเกิดขึ้น ผลที่กิดตามมาอาจจะทำให้เกิดวงจรรอคอย ซึ่งแท้จริงก็คือวงจรอับนั่นเอง วงจรรอคอยในรูปที่ 4.3 เป็นวงจรที่ระบบไม่สามารถแก้ได้ เพราะเงื่อนไขทั้งสามข้อแรกบังคับอยู่ ดังนั้นเงื่อนไขทั้งสี่ข้อจะต้องสมบูรณ์จึงจะทำให้เกิดวงจรอับได้
แผนภาพแสดงของวงจรอับ
เงื่อนไขของวงจรอับทั้งสี่ข้อตามที่ได้กล่าวไปแล้วในหัวข้อที่ผ่านมานั้น เราสามารถอธิบายโดย
ใช้แผนภาพ หรือ กราฟของการจัดสรรทรัพยากรได้ (directed graph) กราฟดังกล่าวประกอบไปด้วยโหนด 2 ประเภท คือ 1 โหนดโปรเซสแสดงเป็นรูปวงกลม และ 2 โหนดทรัพยากรที่แสดงเป็นรูปสี่เหลี่ยม
o ลูกศรจากโหนดทรัพยากรชี้ไปหาโหนดโปรเซส หมายถึง ทรัพยากรนั้นได้ถูกร้องขอและโปรเซสนั้น ก็ได้ใช้ไปแล้ว และกำลังถือครองอยู่ ในรูปที่ 4.4(ก๗ ทรัพยากร R ในขณะนั้นถูกโปรเซส A ถือครองอยู่
o ลูกศรจากโหนดโปรเซสชี้ไปหาโหนดทรัพยากร หมายถึง โปรเซสในขณะนั้นกำลังรอคอยทรัพยากรนั้นอยู่ ในรูปที่ 4.4(ข๗ โปรเซส B กำลังรอทรัพยากร S
ในรูปที่ 4.4 (ค) จะเห็นได้ว่ามีวงจรอับเกิดขึ้น โปรเซส C กำลังรอคอยที่จะใช้ทรัพยากร T ซึ่ง
ในขณะนั้นก็ถูกถือครองโดยโปรเซส D โปรเซส D เองไม่สามารถปล่อยทรัพยากร T ได้ เพราะว่าตัวเองก็กำลังรอคอยทรัพยากร U ที่ถือครองโดยโปรเซส C เช่นกัน โปรเซสทั้งสองก็จะรอคอยอย่างไม่มีที่สิ้นสุด แผนภาพวงกลมในกราฟแสดงว่า วงจรอับนั้นเกี่ยวข้องกับโปรเซสและทรัพยากรที่มีเส้นกราฟต่อกันเป็นลูกโซ่ โดยจากตัวอย่างในรูปนั้น คือ วงจร C-T-D-U- C



รูปที่ 4.4 กราฟการจัดการสรรทรัพยากร การถือครองทรัพยากร (ข) การรอคอยทรัพยากร (ค) วงจรอับ [MOS:P165]
ลองเจาะลึกเข้าไปดูตัวอย่างการใช้งานกราฟการจัดสรรทรัพยากรว่า เราจะสามารถนำไปใช้ประโยชน์
ได้อย่างไรบ้าง สมมุติว่า ในระบบมีโปรเซส 3 ตัว คือ A,B และ C และทรัพยากร 3 ตัว คือ R,S และ T การร้องขอและการปล่อยทรัพยากรของทั้งสามโปรเซสแสดงในรูปที่ 4.5(ก) ถึง (ค) ระบบปฎิบัติการมีอิสระในการอนุญาตเสร็จ ให้โปรเซสใดทำงานหรือป้องกันไม่ให้โปรเซสใดทำงานก็ได้ โดยอาจจะเริ่มจากให้ A ทำงานจนกว่า A จะทำงานเสร็จ และจึงให้ B ทำงานจนเสร็จ แล้ว C จึงทำงานต่อ ลักษณะการกำหนดให้โปรเซสทำงานดังกล่าวจะไม่ทำให้เกิดวงจรอับอย่างแน่นอน เพราะไม่มีการแข่งขันในการใช้ทรัพยากรร่วมกับโปรเซสอื่น ขอยกตัวอย่างการร้องขอ และการปล่อยทรัพยากรเป็นโปรเซสที่ทำการคำนวณแล้วจึงแสดงผล เมื่อโปรเซสทำงานแบบเป็นลำดับ ในขณะที่โปรเซสหนึ่งกำลังรอที่จะแสดงผล จะเป็นไปไม่ได้ที่จะมีโปรเซสอื่นเข้ามาใช้งานซีพียูไปทำการคำนวณ ซึ่งการทำงานแบบนี้จะทำให้ระบบทำงานล่าช้าและไม่มีประสิทธิภาพ อย่างไรก็ตามการทำงานแบบเป็นลำดับก็มีผลดีเหมือนกัน ในกรณีที่ไม่มีโปรเซสใดเลยทำการแสดงผลอยู่ เราก็ควรให้โปรเซสที่สั้นที่สุดทำงานก่อน (shortest job first) ซึ่งจะทำให้ระบบทำงานได้ดีกว่าที่เราจะกำหนดให้โปรเซสมีการทำงานแบบหมุนเวียนกันไป (round robin)
คราวนี้เรามาลองกำหนดให้โปรเซสสามารถทำการคำนวณและแสดงผลพร้อมกันได้ การ
จัดการตารางทำงานที่เหมาะสมควรเป็นการทำงานแบบหมุนเวียนกันไป หรือ round robin นั่นเอง ทรัพยากรอาจจะถูกร้องของดังในรูปที่ 4.5 (ง) ถ้าการร้องขอทรัพยากรทั้ง 6 ครั้งนั้นเกิดขึ้นดังแสดงในรูปที่ 4.5 (จ) –(ญ) หลังจากการร้องขอครั้งที่ 4 เกิดขึ้นโปรเซส A จะถูกบังคับให้รอทรัพยากร S ดังในรูปที่ 4.5 (ซ) และการร้องขอ 2 ครั้งถัดไป โปรเซส B และ C ก็จะถูกบังคับให้รอเช่นกัน ซึ่งทำให้เกิดวงจรลูกโซ่แห่งการรอคอย และเกิดวงจรอับในที่สุด อย่างไรก็ตามระบบปฎิบัติการไม่จำเป็นต้องให้โปรเซสทำงานอย่างเป็นลำดับดังกล่าวก็ได้ ระบบปฎิบัติการเพียงระงับไม่ให้โปรเซสร้องขอทรัพยากรจนกว่าระบบจะอยู่ในสถานะที่ปลอดภัย ในรูปที่ 4.5 ถ้าระบบปฎิบัติการทราบว่าวงจรอับอาจจะเกิดขึ้น ระบบอาจจะระงับไม่ให้โปรเซส B ได้รับทรัพยากร S และให้เพียงโปรเซส A และ C ทำงานก่อน โดยเราจะได้ลำดับของการร้องขอและการปล่อยทรัพยากรดังในรูปที่ 4.5 (ฎ) และลำดับการทำงานของโปรเซสก็สามารถแสดงได้ในรูปที่ 4.5(ฏ)-(ด) ซึ่งทำให้ไม่เกิดวงจรอับขึ้นมาในระบบ และหลังจากโปรเซส A ปลดปล่อยทรัพยกร S ในรูปที่ 4.5(ด) โปรเซส B ก็สามารถใช้ทรัพยากร S ได้เนื่องจาก โปรเซส A ได้ทำงานเสร็จเรียบร้อย และโปรเซส C ก็ได้รับทรัพยากรที่ต้องการไปเรียบร้อยแล้ว ถึงแม้นว่าโปรเซส B จะถูกระงับการใช้งานทรัพยากร T วงจรอับก็จะไม่มีทางเกิดขึ้น เพราะ B เพียงแต่รอให้โปรเซส C ทำงานเสร็จเท่านั้นเอง
ในส่วนนี้อธิบายขึ้นมาเพื่อให้เราทราบถึงประโยชน์ของการนำเอากราฟการจัดสรรทรัพยากร
มาใช้เป็นเครื่องมื่อเพื่อให้เรามองเห็นภาพลำดับการร้องขอและการปลดปล่อยทรัพยากรอย่างเป็นขั้นตอน และในแต่ละขั้นตอนก็ทำการตรวจสอบว่ามีเส้นกราฟที่ทำให้เกิดเป็นวงจรลูกโซ่หรือไม่ ถ้ามีวงจรอับก็จะเกิดขึ้นในระบบ แต่ถ้าไม่มี วงจรอับก็จะไม่เกิดขึ้น
ถึงแม้นว่าในตัวอย่างที่ผ่านมา เราได้เรียนรู้การทำงานาของกราฟการจัดสรรทรัพยากรใน
ลักษณะที่ทรัพยากรแต่ละชนิดมีทรัพยากรเพียง 1 ตัว (Single resource for each type) แต่กราฟนี้สามารถใช้งานในกรณีที่ทรัพยากรแต่ละชนิดมีทรัพยากรหลาย ๆ ตัวก็ได้เช่นกัน หลังจากนี้เราจะเรียนรู้ถึงวิธีการป้องกันไม่ให้ระบบเกิดวงจรอับ ซึ่งโดยทั่วไปแล้ว การจัดการวงจรอับนั้นมีกลยุทธอยู่ 4 วิธี ที่สามารถนำมาใช้ได้คือ
o ทำการป้องกันไว้ก่อน โดยไม่ให้หนึ่งในเงื่อนไขทั้งสี่ข้อของการทำให้เกิดวงจรอับเกิดขึ้น
o ทำการหลีกเลี่ยง โดยการจัดสรรทรัพยากรให้ถูกต้อง
o การตควจพบและแก้ไขคืน เราจะอนุญาตให้วงจรอับเกิดขึ้น และเราค่อยทำการเช็คหาและแก้ไขมัน
o ไม่ต้องสนใจปัญหาใด ๆ เลย ในบางครั้งถ้าเราไม่สนใจปัญหาที่จะเกิดขึ้น ปัญหาก็อาจจะไม่เกิดขึ้น กับคุณก็ได้
เราจะพิจารณาการจัดการกับวงจรอับในแต่ละกลยุทธในรายละเอียดในหัวข้อต่อ ๆ ไป


รูป 4.5 ตัวอย่างการเกิด/หลีกเลี่ยงวงจรอับ แสดงจากกราฟการจัดสรรทรัพยากร [MOS:P166]
การป้องกันการเกิดวงจรอับ (Protection)
วิธีการป้องกันการเกิดวงจรอับ (deadlock prevention) นั้นอาจจะกล่าวได้ง่าย ๆ โดยการออกแบบให้
ระบบมีการป้องกันการเกิดวงจรอับไว้ก่อน จากที่เราได้กล่าวมาในหัวข้อที่ 4.2 เกี่ยวกับเงื่อนไขที่ทำให้เกิดวงจรอับ จะเห็นว่าการป้องกันการเกิดวงจรอับสามารถแบ่งได้เป็น 2 กลุ่ม คือ 1. การป้องกันการเกิดวงจรอับทางอ้อม คือ การป้องกันการเกิดเงื่อนไขสามข้อแรกที่อาจจะทำให้เกิดวงจรอับได้ และ 2 ที่ว่าเงื่อนไขทั้งสี่ข้อจะต้องเกิดขึ้นพร้อมกันจึงจะทำให้เกิดวงจรอับได้ ดังนั้น ถ้าป้องกันไม่ให้เงื่อนไขใดเงื่อนไขหนึ่งเกิดขึ้น เราก็จะสามารถป้องกันการเกิดวงจรอับได้ โดยจะพิจารณาในแต่ละเงื่อนไขดังต่อไปนี้
4.4.1 การใช้ทรัพยากรร่วมกันได้(Mutual exclusion prevention)
ปัญหาในข้อนี้คือ การที่ทรัพยากรในระบบไม่อนุญาตให้โปรเซสหลาย ๆ โปรเซสใช้งานพร้อม ๆ กัน
ได้ ดังนั้นการแก้ปัญหาข้อนี้ ระบบปฎิบัติการจะต้องจัดการให้โปรเซสในระบบสามารถใช้งานทรัพยากรเหล่านั้นร่วมกันได้ ตัวอย่างของทรัพยากรบางประเภท เช่น ไฟล์ข้อมูล ระบบปฎิบัติการอาจจะอนุญาตให้โปรเซสหลาย ๆ โปรเซสเข้าถึงไฟล์ข้อมูลนั้นได้ โดยมีการกำหนดให้มีการเข้าถึงเป็นแบบอ่านได้อย่างเดียว (read only) ก็จะทำให้ไฟล์นั้นสามารถใช้งานร่วมกันได้ และ อนุญาตให้โปรเซสเพียงโปรเซสเดียวเท่านั้นที่ทำการเขียนได้ อย่างไรก็ตาม การป้องกันการเกิดวงจรอับในระบบโดยใช้วิธีนี้ไม่สามารถทำได้เสมอไป เพราะว่ายังมีทรัพยากรบางตัวที่ไม่สามารถใช้งานร่วมกันกับหลาย ๆ โปรเซสพร้อมกันได้ เช่น เครื่องพิมพ์ เป็นต้น (แต่เราก็อาจจะใช้วิธีสพูลลิ่ง (Spooling) เข้า มาช่วยในการจัดการได้ โดยใช้พื้นที่ดิสก์เป็นตัวรับเอาต์พุตแทนเครื่องพิมพ์ แล้วค่อยส่งข้อมูลไปให้เครื่องพิมพ์ ซึ่งวิธีนี้จะทำให้โปรเซสหลาย ๆ ตัวสามารถใช้เครื่องพิมพ์นี้กได้)
4.4.2 การป้องกันการถือครองและรอคอย (Hold and wait prevention)
เงื่อนไขของการถือครองและรอคอยนั้นสามารถป้องกันได้ โดยเราจะอนุญาตให้โปรเซสร้องขอ
ทรัพยากรที่ต้องการทั้งหมดก่อน และจะไม่อนุญาตให้โปรเซสนั้นทำงานจนกว่าจะได้รับทรัพยากรที่ร้องขอไปพร้อมกันทั้งหมดก่อน อย่างไรก็ตาม วิธีการป้องกันแบบนี้จะทำให้ระบบปฎิบัติการทำงานอย่างไม่มีประสิทธิภาพ เพราะอย่างแรกโปรเซสจะต้องถือครองทรัพยากรเป็นเวลานานในขณะที่รอให้ตัวเองได้รับทรัพยากรทั้งหมดก่อนจึงจะทำงานได้ทั้ง ๆ ที่โปรเซสเหล่านั้นเพียงได้รับทรัพยากรบางตัวก็สามารถทำงานก่อนได้เลย อย่างที่สองบางทรัพยากรที่ถูกครอบครองโดยโปรเซสอาจจะยังไม่ได้ถูกใช้งาน และโปรเซสอื่นก้ไม่สามารถเรียกนำไปใช้ได้ด้วย
อย่างไรก็ตามในทางปฏิบัติ เราสามารถพบปัญหาที่ไม่สามารถแก้ไขได้ เช่น ในกรณีที่เราใช้โปรแกรมที่มีโปรแกรมย่อย ๆ หลาย โปรแกรม หรือ โปรแกรมที่มีโครงสร้างที่สามารถทำงานหลาย ๆ อย่างพร้อมกันได้(Multithreaded structure) โปรแกรมเหล่านี้จะต้องทำการตรวจสอบด้วยว่าถ้ามีการร้องขอทรัพยากรจากโปรแกรมย่อย ๆ ภายในพร้อมกัน ทรัพยากรทั้งหมดภายในระบบจะเพียงพอหรือไม่ มิฉะนั้นวงจรอับก็จะเกิดขึ้นได้เช่นกัน
4.4.3 ยอมให้มีการแทรกกลางคัน (Preemptable)
เงื่อนไขนี้เราสามารถทำการป้องกันได้หลาย ๆ วิธี อย่างแรกคือ ถ้าโปรเซสกำลังถือครองทรัพยากร
หนึ่งอยู่ เราจะให้ระบบป้องกันไม่ให้โปรเซสนั้นทำการร้องขอทรัพยากรอื่นใดอีก จนกว่าโปรเซสนั้นจะปลดปล่อยทรัพยากรที่ตัวเองครอบครองเสียก่อน และในบางกรณีถ้าโปรเซสต้องการทรัพยากรเพิ่ม ระบบอาจจะกำหนดให้โปรเซสปล่อยทรัพยากรที่ตัวเองครอบครองอยู่ก่อน และค่อยทำการ้องขอทรัพยากรเหล่านั้นอีกครั้งพร้อมกับ ทรัพยากรที่ต้องการเพิ่มเติม หรือในอีกวิธีหนึ่ง ถ้าโปรเซสต้องการทรัพยากรที่ขณะนั้นถูกถือครองโดยโปรเซสอื่น ระบบปฎิบัติการอาจจะทำการแทรกการทำงานของโปรเซสที่สองและให้โปรเซสนั้นปลดปล่อยทรัพยากร วิธีการที่สองจะป้องกันการเกิดวงจรอับได้ก็ต่อเมื่อ โปรเซสทั้งสองมีสิทธิและความสำคัญที่แตกต่างกัน
4.4.4 การป้องกันการเกิดวงจรรอคอย(Circular wait protection)
การป้องกันสามารถทำได้โดยกำหนดลำดับของทรัพยากรทั้งหมดในระบบ และกำหนดให้โปรเซส
ต้องร้องขอใช้ทรัพยากรเรียงตามลำดับนี้ เช่น ถ้าโปรเซสกำลังถือครองทรัพยากร S อยู่ และต่อมาโปรเซสนี้ได้ทำการร้องขอทรัพยากร ซึ่งระบบจะอนุญาตให้โปรเซสนั้นร้องขอได้เฉพาะทรัพยากรที่อยู่ในลำดับที่สูงกว่า S
เพื่อให้เรามองเห็นภาพที่ชัดเจนขึ้น เราจะกำหนดให้ทรัพยากร Ri มาก่อน Rj ในลำดับของเงื่อนไขที่ว่า I < j และลองพิจารณาโปรเซส A และ B ที่จะทำให้เกิดวงจรอับ โดยวงจรอับจะเกิดขึ้นก็ต่อเมื่อ A กำลังถือครองRi และ ทำการร้องขอ Rj และ B ก็กำลังถือครอง Rj และทำการร้องขอ Ri ซึ่งมีความเป็นไปไม่ได้เพราะว่าเกิดความขัดแย้งในข้อกำหนดที่เราได้ตั้งไว้ก่อนหน้าคือ i < j แต่ถ้า B ทำการร้องขอ Ri ได้ก็หมายความว่า j < I ซึ่งถ้าระบบปฎิบัติการทำตามข้อกำหนดก็จะทำไม่ให้เกิดวงจรรอคอยดังกล่าว โปรดสังเกตว่าการกำหนดค่าเลขลำดับของทรัพยากรนั้น ควรเรียงตามลำดับการใช้งานของระบบตามปกติ เช่น ปกติเราจะใช้ไฟล์ข้อมูลก่อนเครื่องพิมพ์เสมอ ระบบก็ควรจะกำหนดลำดับของไฟล์ข้อมูล < ลำดับของเครื่องพิมพ์
อย่างไรก็ตามการป้องกันวิธีนี้จะส่งผลให้การทำงานของระบบปฎิบัติการไร้ประสิทธิภาพเช่นเดียวกับการป้องกันการถือครองและรอคอย(Hold and wait) โดยจะทำให้การประมวลผลช้าลงและมีการปฎิเสธการใช้งานของทรัพยาการโดยไม่มีความจำเป็น
จากการป้องกันการเกิดวงจรอับตามที่ได้กล่าวมาแล้วข้างต้นเราสามารถสรุปได้เป็น
เงื่อนไข วิธีการ
การใช้ทรัพยากรร่วมกันไม่ได้
การถือครองและรอคอย
การไม่การแทรกกลางคัน
การเกิดวงจรรอคอย ให้ใช้ทรัพยากรที่สามารถใช้ร่วมกันได้ เช่น ดิสก์ในการจัดการสพูลลิ่ง
ให้โปรเซสร้องขอทรัพยากรทั้งหมดก่อน
ให้ระบบสามารถแทรกการทำงานและเรียกคืนทรัพยากรได้
จัดเรียงและใช้ทรัพยากรอย่างเป็นลำดับ
การหลีกเลี่ยงการเกิดวงจรอับ (Avoidance)
ในหัวข้อ 4.4 ที่ผ่านมา เสนอการป้องกันการเกิดวงจรอับขึ้นมาในระบบ โดยสร้างข้อกำหนดของการร้อง
ขอทรัพยากร เพื่อให้แน่ใจว่าเงื่อนไขเพียงข้อใดข้อหนึ่งที่เป็นสิ่งจำเป็นในการเกิดกวงจรอับจะไม่เกิดขึ้นอย่างแน่นอน แต่การกำหนดเหล่านั้นอาจจะมีผลกระทบต่อการทำงาานของระบบได้ เช่น การใช้งานทรัพยากร หรือการทำงานของโปรเซสในระบบจะมีประสิทธิภาพต่ำลง
อีกทางเลือกหนึ่งที่จะทำให้ระบบสามารถหลีกเลี่ยงการเกิดวงจรอับได้ โดยอนุญาตให้เงื่อนไขสามข้อแรก
สามารถเกิดขึ้นได้ แต่จะให้ระบบใช้วิจารณญาณในการเลือกที่จะไม่ทำให้เกิดวงจรอับขึ้นมา กล่าวคือ ระบบจะต้องมีความสามารถในการตัดสินใจว่า ในการที่โปรเซสร้องขอทรัพยากรหนึ่ง ๆ นั้นจะทำให้ระบบปลอดภัยหรือไม่ และจะอนุญาตให้โปรเซสนั้นได้รับทรัพยากรถ้าระบบปลอดภัยเท่านั้น ดังนั้น จึงมีคำถามตามมาว่า มีวิธีการคิดใด หรือไม่ที่เราจะสามารถหลีกเลี่ยงวงจรอับได้ โดยทำการเลือกตัวเลือกที่ถูกต้องทุกครั้ง ถ้ามีคำตอบที่บอกว่า “ใช่ไ เราก็สามารถหลีกเลี่ยงวงจรอับได้ แต่ก่อนที่ระบบจะเลือกตัวเลือกที่ถูกต้องได้นั้น ข้อมูลทั้งหมดของระบบจะต้องถูกจัดเตรียมไว้ก่อนแล้ว
4.5.1 แนวเส้นของการใช้ทรัพยากร
วิธีการคิด หรืออัลกอริทึ่มขงการหลีกเลี่ยงการเกิดวงจรอับวิธีนี้มีพื้นฐานอยู่บนแนวความคิดของการที่เรา
ต้องการให้ระบบอยู่ในสถานะที่ปลอดภัย(safe state) และก่อนที่เราจะเรียนรู้ในรายละเอียดของวิธีการคิดแบบนี้ แผนภาพจะถูกใช้เพื่อแสดงแนวความคิดของคำว่า “อยู่ในสถานะที่ปลอดภัย” ถึงแม้ว่า ในบางครั้งการใช้แผนภาพจะไม่สามารถสื่อความหมายโดยตรงเกี่ยวกับการใช้อัลกอริทึ่มนี้ก็ตาม แต่มันก็สามารถทำให้เราเข้าใจ ความหมายของปัญหาและหนทางแก้ไขได้มากขึ้น


รูปที่ 4.6 ตารางการใช้ทรัพยากรของโปรเซส 2 ตัว [MOS:P176]

ในรูปที่ 4.6 จะแสดงให้เห็นถึงรูปแบบของการจัดการวงจรอับที่เกิดจากโปรเซส 2 ตัว และทรัพยากร 2 ตัว
ตัวอย่างเช่น เครื่องพิมพ์ 1 เครื่อง และเครื่องพล็อตเตอร์ 1 เครื่อง จากกราฟในแนวนอนแสดงถึงจำนวนคำสั่งที่เรียกใช้โดยโปรเซส A ส่วนกราฟในแนวตั้งจะแสดงถึงจำนวนคำสั่งที่เรียกใช้โดยโปรเซส B ณ จุด l1 โปรเซส A ได้ร้องขอที่จะใช้เครื่องพิมพ์ และที่จุด l 2 ก็ต้องการใช้เครื่องพล็อตเตอร์ด้วยเช่นกัน จากนั้นเครื่องพิมพ์แลเครื่องพล็อตเตอร์จะถูกปล่อยคืนสู่ระบบ ณ จุด l3 และ l4 ตามลำดับ ส่วนโปรเซส B ก็ต้องการเครื่องพล็อตเตอร์จาก l5 ถึง l7 และต้องการเครื่องพิมพ์จาก l6 ถึง l8 ทุก ๆ จุดบนแผนภาพจะแสดงถึงสถานะความสัมพันธ์ของทั้งสองโปรเซส เริ่มต้นจากจุด p ในแผนภาพ ณ จุดนี้จะไม่มีโปรเซสใดได้เรียกใช้คำสั่งใด ๆ เลย และถ้าระบบกำหนดให้โปรเซส A เริ่มทำงานก่อน เราก็จะมาอยู่ที่จุด q ที่ซึ่ง A ได้เรียกใช้คำสั่งบางคำสั่งแต่ B ยังไม่ได้เรียกใช้อะไรเลย ที่จุด q เส้นกรากฟเดินทางในแนวตั้ง ซึ่งแสดงว่าระบบเริ่มกำหนดตารางให้ B ทำงาน ถ้าในระบบที่มีตัวประมวลผลเพียง 1 ตัว แนวเส้นจะอยู่ในแนวนอนหรือแนวตั้งเท่านั้นและจะไม่มีเส้นทะแยงมุมเป็นอันขาด นอกจากนี้ทิศทางการเดินก็จะอยู่ในทิศเหนือ หรือทิศตะวันออกเท่านั้น(โปรเซสไม่สามารถทำงานย้อนกลับได้) ส่วนพื้นที่แรเงาก็จะแสดงถึงพื้นที่ที่โปรเซสทั้งสองใช้งานทรัพยากรเดียวกัน โดยพื้นที่แรเงาจากด้านล่างซ้ายไปฝั่งบนขวาแทนการใช้งานเครื่องพิมพ์พร้อมกัน และพื้นที่แรเงาในด้านตรงกันข้ามแทนการใช้งานเครื่องพล็อตเตอร์พร้อมกัน อย่างไรก็ตามโดยเงื่อนไขของการใช้ทรัพยากรร่วมกันไม่ได้ หรือ Mutual exclusive นั้นทำให้แนวเส้นการใช้ทรัพยากรไม่สามารถเดินทางเข้าไปในพื้นที่เหล่านี้ได้
เราจะเริ่มพิจารณาแนวเส้นในแผนภาพกันต่อ โดยเมื่อโปรเซส A ได้เดินไปในแนวทางจาก r ถึง s โปรเซส A ได้ร้องขอและได้ใช้งานเครื่องพิมพ์แล้ว เช่นเดียวกันเมื่อถึงจุด t โปรเซส B ก็ทำการร้องขอใช้เครื่องพล็อตเตอร์ หลังจากจุด t ถ้าแนวเส้นการใช้ทรัพยากรเข้าไปในกรอบระหว่าง l1, l2 และ l5,l6 ก็จะทำให้เกิดวงจรอับขึ้นในระบบ เมื่อแนวเส้นเดินทางไปถึงจุดตัดระหว่าง l2 และ l6 ณ จุดนั้น A จะร้องขอใช้เครื่องพล็อตเตอร์ และ B ก็ร้องขอใช้เครื่องพิมพ์ แต่ทรัพยากรทั้งคู่ก็ถูกครอบครองอยู่ ดังนั้นพื้นที่ของกรอบดังกล่าวจะแทนสถานที่ไม่ปลอดภัย (unsafe sate) และเราไม่ควรให้แนวเส้นการใช้ทรัพยากรเดินเข้าไป ณ จุด t การทำงานที่ปลอดภัยก็คือ ให้โปรเซส A ทำงานจนถึงจุด l4 และหลังจากนั้นแนวเส้นก็สามารถเดินไปถึงจุด u ได้
ข้อคิดที่สำคัญที่เราควรมองเห็นคือ ณ จุด t โปรเซส B กำลังร้องขอใช้ทรัพยากร ระบบจะต้องตัดสินใจว่าจะให้ทรัพยากรกับโปรเซสหรือไม่ ถ้าให้ไป ระบบก็จะเจ้าสู่สถานะทีไม่ปลอดภัยและก็อาจจะเกิดวงจรอับในที่สุด ถ้าจะหลีกเลี่ยงวงจรอับ B จะต้องถูกระงับไม่ให้ทำงานจนกระทั่ง A ได้ใช้งานและปลดปล่อยเครื่องพล็อตเตอร์กลับคืนสู่ระบบเรียบร้อยแล้ว
จะเห็นได้ว่าการหลีกเลี่ยงไม่ให้เกิดวงจรอับขึ้นมาในระบบนั้น ระบบจำเป็นต้องรู้ความต้องการทรัพยากร ทั้งหมดของโปรเซสที่เกิดขึ้นในอนาคตก่อนเสมอ และเราสามารถหลีกเลี่ยงวงจรอับได้โดย
1. ไม่อนุญาตให้โปรเซสทำงานถ้าทรัพยากรที่ร้องขออาจทำให้เกิดวงจรอับได้
2. ไม่อนุญาตให้ทรัพยากรเพิ่มแก่โปรเซสที่ร้องขอ ถ้าการครอบครองของโปรเซสอาจทำให้เกิดวงจรอับได้
4.5.2 การปฏิเสธให้โปรเซสทำงาน
ให้เราลองพิจารณาระบบที่มีโปรเซส n ตัว และมีทรัพยากรต่างชนิดกัน m ตัวให้เรานิยมเวกเตอร์และแมตทริกซ์ ของทรัพยากรได้ดังนี้
Resource = (R1,R2,…,Rm) จำนวนทรัพยากรแต่ละชนิดทั้งหมดในระบบ
Available = (V1,V2,…,Vm) จำนวนทรัพยากรทั้งหมดที่ไม่ได้ถูกครอบครอง

Claim = ความต้องการทรัพยากรแต่ละชนิดของแต่ละโปรเซส
Allocation = ทรัพยากรแต่ละชนิดที่ถูกครอบครองโดยแต่ละโปรเซส

แมตทริกซ์ Claim แสดงถึงความต้องการทรัพยากรแต่ละชนิดสูงสุดของแต่ละโปรเซส โดยให้แต่ละแถวแทนโปรเซส 1 ตัว นั่นคือ

Cij = จำนวนทรัพยากร j ที่โปรเซส i ต้องการ
และข้อมูลดังกล่าวจะต้องทำการประกาศก่อนหน้าขั้นตอนที่ใช้ในการหลีกเลี่ยงวงจรอับทำงานได้ และเช่นเดียวกับ A=จำนวนทรัพยากร j ที่ถูกครอบครองโดยโปรเซส i นอกจากนี้ความสัมพันธ์ต่างๆจะต้องเป็นไปตามข้อมูลด้านล่างนี้
1.Ri = Vi+Aki สำหรับทุกๆค่าของ I; ทรัพยากรทั้งหมดเท่ากับทรัพยากรที่ว่างบวกกับที่ถูก
ครอบคองอยู่
2.Cki ≤ Ri สำหรับทุกคำสั่งของ k,I; ไม่มีโปรเซสใดที่สามารถร้องขอมากได้กว่าจำนวน
ทรัพยากรที่มีอยู่ทั้งหมด
3. Aki ≤ Cki สำหรับทุกค่าของ k,I; ไม่มีโปรเซสใดที่สามารถครอบครองทรัพยากรมากกว่า
ที่ตัวเองร้องขอในตอนแรก
จากข้อกำหนดด้านบน เราสามารถกำหนดนโยบายของการหลีหเลี่ยงวงจรอับได้ว่า เราไม่อนุญาตให้โปรเซสใดทำงาน ถ้าความต้องการทรัพยากรของโปรเซสนั้นจะนำพาระบบเข้าสู่วงจรอับได้ นั่นคือ เราจะเริ่มโปรเซสPn+1ใหม่ก็ต่อเมื่อ
Ri > = C(n+1) I + Cki สำหรับทุกค่าของ i
นั่นคือโปรเซสหนึ่งจะสามารถทำงานได้ก็ต่อเมื่อ จำนวนทรัพยากรแต่ละชนิดที่โปรเซสต้องการทั้งหมดรวมกับ จำนวนทรัพยากรแต่ละชนิดที่โปรเซสใหม่ต้องการ จะต้องไม่เกินจำนวนทรัพยากร
ที่มีอยู่ในระบบทั้งหมด อย่างไรก็ตามวิธีนี้อาจจะทำให้การทำงานไม่มีประสิทธิภาพมากหนัก เพราะโปรเซสทั้งหมดจะต้องทำการร้องขอทรัพยากรสูงสุดก่อน
4.5.3การปฏิเสธไม่ให้ครอบครองทรัพยากร
วิธีการครอบครองทรัพยากร หรือที่เรารู้จักกันดีในชื่อของ “วิธีการทำงานของนายธนาคาร”
(Banker’s Algorithm)ซึ่งหมายถึงเป็นการแก้ปัญหาของธนาคารในกรณีที่มีลูกค้าต้องการกู้ยืมเงินซึ่งมีลักษณะการทำงานเหมือนโปรเซสที่ใช้ทรัพยากรในระบบปฏิบัติการทั่วๆไป (ลูกค้าเปรียบเสมือนโปรเซส และเงินที่ถูกยืมเปรียบเสมือนทรัพยากร) จากวิธีการทำงานของธนาคารนั้น ธนาคารจะมีจำนวนเงินที่ให้ลูกค้ากู้ยืมที่จำกัด และก็มีรายชื่อของลูกค้าพร้อมกับเครดิตที่แต่ละตนจะได้รับ ลูกค้าบางคนอาจจะพยายามกู้เงินให้ได้เต็มเครดิตที่ตัวเองมี และบางครั้งลูกค้าคนนั้นก็ไม่ยอมจ่ายเงินคืนกลับให้ธนาคารจนกว่าจะได้รับจำนวนเงินที่ต้องการกู้ยืมทั้งหมด แต่นายธนาคารเองก็สามารถปฏิเสธการกู้ยืมของลูกค้าบางคนได้ ถ้าการปล่อยกู้ยืมครั้งนั้นจะทำให้เกิดความเสี่ยงทำให้ธนาคารมีเงินไม่เพียงพอที่จะให้ผู้นั้นได้กู้ยืมเพิ่มเติม และลูกค้าคนนั้นก็ไม่สามารถใช้เงินคืนแก่ธนาคารได้ รายละเอียดของการทำงานแบบนายธนาคารกับระบบที่มีทรัพยากรเพียง1ตัวจะอธิบายดังด้านล่างนี้ ส่วนการจัดการกับระบบที่มีทรัพยากรหลายๆตัวนั้นเราจะอธิบายในรายละเอียดในหัวข้อต่อไปนี้
จากในหัวข้อที่4.5.2 ณ เวลาใดก็ตาม สถานะของระบบขึ้นอยู่กับค่าของ R ,V,C และ A และสถานะของระบบจะปลอดภัยเมื่อไม่มีวงจรอับเกิดขึ้น ดังนั้นเราต้องจัดลำดับการทำงานให้กับทุกๆโปรเซสให้สามารถทำงานจนเสร็จสิ้นสมบูรณ์ ถึงแม้ว่าโปรเซสทั้งหมดำด้ร้องขอทรัพยากรตามโควต้าสูงสุดที่ได้รับพร้อมกัน เราจะใช้แผนภาพในรูปที่4.7 แสดงตัวอย่างของการจัดการใช้ทรัพยากร1ตัวโดยรูป4.7 (ก) โปรเซส A ได้รับทรัพยากรนั้นมา 3 ตัว แต่ต้องการทั้งหมด 9 ตัว, B ได้รับ 2 ตัว และต้องการทั้งหมด 4 ตัว เช่นเดียวกับ C ได้รับ 2 ตัว แต่ต้องการเพิ่มอีก 5 ตัว (ต้องการทั้งหมด 7ตัว) สมมุติว่าทรัพยากรนี้ 10 ตัว ในระบบแลโปรเซสได้ถือครองไปแล้ว 7 ตัวจึงเหลืออีก 3 ตัว

รูปที่4.7การแสดงของสถานะทำงานที่ปลอดภัย[MOS:P177]
สถานะของรูป4.7 (ก) นั้นปลอดภัย เพราะว่าเราสามารถกำหนดลำดับการครอบครองทรัพยากรของ โปรเซสแต่ละชนิดให้สามารถทำงานจนเสร็จสมบูรณ์ ได้ โดยเราอาจจะกำหนดการทำงานได้ดังนี้
• ให้โปรเซส B ทำงานก่อน เสร็จโดยให้ทรัพยากรเพิ่ม 2 ตัว ดังรูป4.7 (ข)
• เมื่อ B ทำงานจนเสร็จ B ก็จะคืนทรัพยากรกลับสู่ระบบ ดังรูป 4.7(ค)
• กำหนดให้ C ทำงานโดยให้ทรัพยากรเพิ่มดังรูป4.7 (ง)
• เมื่อ C ทำงานจนเสร็จสมบูรณ์แล้ว เราก็จะได้ผลดังในรูปที่4.7(จ) ซึ่ง ณ จุดนี้ A ก็สามารถใช้ทรัพยากรเพิ่มและทำงานจนเสร็จสมบูรณ์ได้
เราจะเห็นได้ว่าระบบของรูปที่ 4.7นั้น อยู่ในสถานะที่ปลอดภัย เพราะว่าระบบได้กำหนดการทำงานของโปรเซสได้อย่างถูกต้องและสมารถหลีกเลี่ยงวงจรอับได้



รูป4.8การแสดงของสถานะทำงานที่ไม่ปลอดภัย[MOS:P177]
คราวนี้เรามาลองพิจารณาตัวอย่างอีกตัวอย่างหน฿งกันในรูป4.8(ก)แต่คราวนี้โปรเซสA ได้รับขอและได้รับทรัพยากรเพิ่มมาอีก 1 ตัว ดังในรูปที่4.8(ข)ระบบจะสามารถหาหนทางที่จะทำให้โปรเซสแต่ละอันทำงานจนเสร็จสมบูรณ์ได้หรือไม่ โดยทดลองให้B ทำงานโดยทำการให้ทรัพยากรเพิ่มเติมกับ B ดังในรูปที่4.8(ค)และในที่สุดB ก็จะทำงานเสร็จและคืนทรัพยากรกลับสู่ระบบดังรูปที่4.8(ง) ณ จุดนี้ระบบมีทรัพยากรเหลือ4ตัวแต่โปรเซสที่เหลือต่างต้องการทรัพยากรอย่างน้อย5ตัว จึงจะสามารถทำงานได้ ดังนั้นการที่ระบบตัดสินใจให้ทรัพยากรจากรูปที่4.8(ก)ไปสู่รูปที่4.8(ข)เป็นการตักสินใจที่นำพาระบบเข้าสู่สถานะที่ไม่ปลอดภัย และแม้นระบบจะให้โปรเซสAหรือCทำงานหลังจากนั้นก็ไม่ส่งผลสำเร็จทั้งคู่ ดังนั้น ถ้าเราพิจารณาย้อนกลับไป ระบบควรปฏิเสธการร้องขอของโปรเซสA
แต่อย่างไรก็ตามเมื่อระบบเข้าสู่สถานะที่ไม่ปลอดภัยก็ไม่ได้หมายความว่า ระบบจะเข้าสู่วงจรอับเสมอถ้าพิจารณากลับไปที่รูป 4.8(ข) ระบบสามารถทำงานได้สักระยะหนึ่ง ซึ่งก็ทำโปรเซสB ทำงานจนเสร็จและนอกจากนี้ มันก็มีความเป็นไปได้ว่า A อาจจะทำการปล่อยทรัพยากรมาสัก1ตัวก่อนทำการร้องขอทรัพยากรเพิ่มซึ่งก็ทำให้C ทำงานจนสำเร็จและวงจรอับก็ไม่เกิดขึ้นในระบบ ดังนั้นข้อแตกต่างของสถานะที่ปลอดภัยและสถานะที่ไม่ปลอดภัยก็คือ ในสถานะที่ปลอดภัย เราสามารถทำการยืนยันว่าโปรเซสทุกตัวในระบบจะทำงานเสร็จสิ้นสมบูรณ์และไม่เกิดวงจรอับ แต่ในสถานะที่ไม่ปลอดภัยนั้นเราไม่สามารถทำการยืนยันได้เท่านั้นเอง ซึ่งวงจรอับอาจจะเกิดขึ้นก็ได้ในระบบ ดังแสดงในแผนภาพในรูปที่ 4.9

รูป 4.9 เซ็ตในระบบที่แทนสถานะที่ปลอดภัย,สถานะที่ไม่ปลอดภัย และการเกิดวงจรอับ[OSC6:P254]
4.5.4 วิธีการทำงานแบบนายธนาคารสำหรับระบบที่มีทรัพยากรหลายตัว


รูปที่ 4.10 หารใช้ banker’s algorithm กับระบบบมีทรัพยกรหลายตัว[MOS:P179]
วิธีการทำงานแบบนายธนาคารสามารถจัดการกับระบบที่มีทรัพยากรหลายๆ ตัว โดยแมทริกซ์ด้านซ้ายแสดงถึงจำนวนทรัพยากรแต่ละชนิดที่ถูกกระบวนทั้ง5ตัวครอบครองในขณะนั้นและแมทริกซ์
ด้านขวามือแสดงถึงจำนวนทรัพยากรที่แต่ละโปรเซสต้องการเพิ่มเติมเพื่อให้สามารถทำงานจนเสร็จสมบูรณ์ได้ แมทริกซ์เหล่านี้แสดงถึงตัวแปร A และ C ตามลำดับ เช่นเดียวกับการพิจารณาทรัพยากรตัวเดียว โปรเซสทุกตัวต้องทำการประกาศทรัพยากรทั้งหมดที่ต้องการ (C) ก่อนที่ระบบจะเริ่มทำงานได้ ดังนั้นแมทริกซ์ด้านขวามือก็คือจำนวนทรัพยากรที่ต้องการทั้งหมดของแต่ละกระบวน ณ ขณะใดขณะหนึ่งนั่นเอง
ส่วนเวกเตอร์สามตัวทางด้านขวามือแสดงถึงจำนวนทรัพยากรทั้งหมด R จำนวนทรัพยากรที่ถูกครอบครองขณะนั้น P และ จำนวนทรัพยากรแต่ละชนิดที่ยังคงว่างอยู่ V ตามลำดับ จากเวกเตอร์ R เราจะเห็นว่าในระบบ มีเทปบันทึกข้อมูล 6 ตัวพล็อตเตอร์ 3 ตัวและเครื่องพิมพ์ 4 ตัวและไดร์ซีดีรอม 2 ตัวจากจำนวนเหล่านี้ มีทรัพยากรที่ถูกใช้ไปแล้ว คือ เทปบันทึกข้อมูล 5 ตัวพล็ตเตอร์ 3 ตัว เครื่องพิมพ์ 2 ตัว และไดร์ซีดีรอม 2 ตัว โดยสามารถคำนวณได้จากผลรวมของแต่คอลัมน์ของแมทริกซ์ทางด้านซ้ายมือ(A)และเวกเตอร์V คือผลต่างของทรัพยากรที่ถูกครอบครองไปแล้วนั่นเอง (R-P)
วิธีการคิดที่ใช้ตรวจสอบดูว่าระบบอยู่ในสถานะที่ปลอดภัยหรือไม่ ทำได้โดย
1.เริ่มตรวจสอบที่แถว ของโปรเซสในตารางแมทริกซ์ C ให้ดูว่าแถวไหนบ้างที่มีจำนวนทรัพยากรแต่ละตัวที่ต้องการน้อยกว่าหรือเท่ากับเวกเตอ์ V หรือไม่ ถ้าไม่มีแสดงว่าวงจรเข้าสู่ระบบวงอับเรียบร้อยแล้ว เพราะว่าไม่มีโปรเซสใดที่สามารถทำงานได้สำเร็จ
2.สมมุติว่ามีอยู่ 1 แถว ที่สามารถได้รับทรัพยากรแต่ละตัวที่ต้องการทั้งหมด (อย่างเช่น โปรเซส D ) และทำงานได้ ให้เราทำเครื่องหมายว่าโปรเซสนั้นทำงานจนเสร็จสิ้น และส่งคืนทรัพยากรเข้าสู่ระบบโดยทำการบวกทรัพยากรที่โปรเซสนั้นได้รับกลับสู่เวกเตอร์ V
3.ทำข้อ 1 และข้อ 2 ซ้ำ จนกระทั่งทุกๆ โปรเซสทำงานเสร็จเรียบร้อย โดยทุกงานสามารถทำงานได้เสร็จก็หมายความว่าระบบอยู่ในสถานะที่ปลอดภัย แต่ถ้ามีวงจรอับเกิดขึ้นดังอธิบายในข้อ 1 ก็หมายความว่าระบบไม่อยู่ในความปลอดภัยแน่นอน
เราลองกลับไปพิจารณารูป4.10 เป็นตัวอย่างจะเห็นว่า สถานะของระบบนั้นปลอดภัย ถึงแม้นว่าโปรเซส B จะร้องขอใช้เครื่องพิมพ์เพิ่ม ระบบก็สามารถให้ได้เพราะว่าระบบก็ยังอยู่ในสถานะที่ปลอดภัย ก็คือ โปรเซส D สามารถทำงานให้แล้วเสร็จได้ จากนั้น ก็ให้โปรเซส A หรือ E ทำงาน และให้โปรเซสที่เหลือทำหลังจากนั้น (เช่น D,A,E,B,และ C)
แต่อีกกรณีหนึ่ง หลังจากที่ B ได้รับ 1 ใน 2 เครื่องพิมพ์ที่เหลือ, E ก็ต้องการเครื่องพิมพ์เครื่องสุดท้ายนั้น ถ้าระบบให้เครื่องพิมพ์ไปตามคำร้องขอ เวกเตอร์ V ก็จะเหลือค่า [1000] ซึ่งทำให้เกิดวงจรอับ ดังนั้นระบบจะต้องปฏิเสธการร้องขอของ E จนกว่าระบบจะออกจากสถานะที่ไม่ปลอดภัย
ถึงแม้ว่าขั้นตอนและวิธีการทำงานแบบนี้จะดีอย่างไรก็ตาม ในระบบปฏิบัติการคอมพิวเตอร์จริง ๆ นั้นการใช้วิธีการแบบนี้เป็นไปได้ยากมาก เพราะการที่โปรเซสต่าง ๆ จะรู้ล่วงหน้าถึงจำนวนทรัพยากรที่ตัวเองต้องการก่อนทำงานนั่นมีความเป็นไปได้น้อยมากหรือแทบไม่มีเลย และจำนวนของโปรเซสก็ไม่คงที่ด้วย เช่น ในกรณีที่มีผู้ใช้ใหม่ ๆ เข้ามา หรือออกไปจากระบบ หรือทรัพยากรบางอย่างที่ระบบคิดว่ามีอยู่แต่พอใช้งานจริง ๆ อาจจะสูญหายหรือเสียไปก็ได้ เช่น ดิสก์เสียโดยกระทันหัน (damaged sector)
4.6วิธีการตรวจสอบและกู้คืนเมื่อเกิดวงจรอับ
วิธีการป้องกันการเกิดวงจรอับที่ผ่านมานั้นค่อนข้างส่งผลให้ระบบทำงานอย่างไม่เต็มประสิทธิภาพส่วนมากจะแก้ปัญหาโดยการจำกัดสิทธิในการใช้งานทรัพยากร หรือ โดยการกำหนดข้อห้ามกับโปรเซสที่ต้องการทำงาน แต่การจัดการวงจรอับที่เราจะศึกษาในหัวข้อนี้จะมีวิธีการที่ตรงกันข้ามกับที่เคยกล่าวมาแล้ว คือการตรวจสอบและกู้คืนจะไม่จำกัดสิทธิใด ๆ ในการใช้งานทรัพยากร หรือกำหนดข้อบังคับแก่โปรเซสแต่อย่างไร วิธีการนี้โปรเซสที่ร้องขอทรัพยากรจะได้รับทรัพยากรนั้นเสมอถ้าเป็นไปได้ แต่ระบบจะต้องมีวิธีการที่สามารถทำการตรวจสอบได้ว่ามีวงจรรอคอยเกิดขึ้นมาในระบบหรือไม่ ถ้ามีก็ต้องทำการแก้ไขหรือกู้คืนระบบให้อยู่ในสภาวะปกติต่อไป
4.6.1.ขั้นตอนของการตรวจหาวงจรอับ
การตรวจสอบว่าเกิดวงจรอับเกิดหรือไม่ เราสามารถทำได้ทุกครั้งที่ทรัพยากรในระบบถูกร้องขอ หรือจะทำน้อยครั้งกว่านั้นก็ได้ขึ้นอยู่กับว่าในระบบนั้นมีความน่าจะเป็นที่จะเกิดวงจรอับมากน้อยเพียงใด การตรวจสอบระบบทุกครั้งที่มีการร้องขอทรัพยากร มีข้อดีอยู่2ข้อคือ 1.เราสามารถตรวจพบวงจรอับได้เร็ว และ 2.เราสามารถกำหนดเวลาทำงานได้ง่าย แต่ในทางตรงข้ามกันการตรวจสอบระบบบ่อยครั้งก็เป็นการเปลืองเวลาของตัวประมวลผลในการทำงานเช่นกัน
ตัวอย่างของอัลกอริทึ่มที่ใช้ในการตรวจสอบสามารถอธิบายได้โดยใช้แมตทริกซ์ที่ได้เคยกล่าวไว้ในหัวข้อ4.5.2 นอกเหนือจากแมตทริกซ์จำนวนของทรัพยากรแต่ละชนิดที่๔กครอบครอง (Allocation) และเวกเตอร์จำนวนของทรัพยากรที่เหลืด (Available) ที่เราจะนำมาใช้แล้ว ยังมีแมตทริกซ์Q ที่เรานิยามให้ qij แทนจจำนวนทรัพยากรชนิด j ที่ถูกร้องขอโดยโปรเซส i อัลกอริทึมนี้ทำงานได้โดยอาศัยหลักการทำเครื่องหมายให้กับโปรเซสที่ไม่อยู่ในวงจรอับดังนี้
1.แรกเริ่มโปรเซสทั้งหมดจะไม่มีเครื่องหมายใดๆ
2.จากนั้นทำเครื่องหมายบนโปรเซสทุกตัวที่มีค่าของแถวใน A เป็นศูนย์หมด
3.สร้างเวกเตอร์ชั่วคราว W ให้มีค่าเท่ากับเวกเตอร์ V
4.ค้นหาตำแหน่งแถว i โดยที่โปรเซส i จะต้องไม่ถูกทำเครื่องหมายแล้ว และแถวที่ i ของ Q มีค่า
น้อยกว่าหรือเท่ากับ W นั่นคือ Qik<=Wk, สำหรับทุกค่าของ 1<=k <=m ถ้าไม่พบแถวตามที่
กำหนดให้หยุดการทำงาน
5.ถ้าพบแถวที่ตรงตามเงื่อนไข ให้ทำเครื่องหมายที่โปรเซส i และเพิ่มค่าของ W โดยการบวกเพิ่ม
ค่าของแถวที่ตรงกันในแมตทริกซ์ A นั่นคือให้ Wk =Wk + Aik
วงจรอับจะเกิดขึ้นก็ต่อเมื่อมีโปรเซสที่ไม่ถูกทำเครื่องหมายเมื่อจบการทำงาน และโปรเซสที่ไม่มีเครื่องหมายนั้นก็อยู่ในวงจรอับนั่นเอง วิธีการคิดแบบนี้สร้างขึ้นเพื่อค้นหาโปรเซสที่ร้องขอทรัพยากรที่ระบบสามารถให้ได้ และเมื่อให้ทรัพยากรแล้วโปนรเซสนั้นสามารถทำงานจนจบและคืนทรัพยากรกลับสู่ระบบ
พึ่งสังเกตว่าวิธีการแบบนี้จะไม่มีการป้องกันการเกิดวงจรอับเลย เพราะการเกิดวงจรอับขึ้นอยู่กับลำดับของการให้ทรัพยากรแก่โปรเซสที่ร้องขออีกที ขั้นตอนที่กล่าวมาข้างต้นเป็นเพียงการตรวจหาว่าเกิดวงจรอับขึ้นในระบบหรือไม่เท่านั้น

รูป4.11 ตัวอย่างของวิธีการตรวจหาวงจรอับ[OSID:P268]
เรามาทดลองดูตัวอย่างดังรูปที่4.11ซึ่งจะแสดงวิธีการตรวจหาวงจรอับได้ดังนี้
1.ทำเครื่องหมายที่กระบวน P4เพราะว่า P4 ไม่มีทรัพยากรในครอบครองเลย
2.กำหนดให้ W=[00001](เท่ากับ เวกเตอร์ aVailable)
3.ทรัพยากรที่โปรเซส P3 ต้องการนั้นน้อยกว่าหรือเท่ากับ W ดังนั้น ให้ทำเครื่องหมายที่ P3 และเพิ่มค่า W =W + [00010]=[00011]
4.ออกจากการตรวจสอบ
จะเห็นว่าผลการตรวจสอบจบลงตรงที่ P1 และ P2 ไม่ถูกทำเครื่องหมายใด ๆ ซึ่งเป็นตัวบอกว่าวงจรอับจะเกิดขึ้นกับโปรเซสเหล่านี้
2.การกู้คืนระบบ
1.ยกเลิกการทำงานของแต่ละโปรเซสที่เกิดวงจรอับทีละตัว จนกว่าไม่มีวงจรอับเกิดขึ้นในระบบ โดยลำดับของโปรเซสที่ถูกเลือกให้ยกเลิกนั้นควรเลือกตามเกณฑ์ที่จะทำให้ระบบสูญเสียน้อยที่สุดโดยสามารถใช้หลักเกณฑ์
- เลือกโปรเซสที่ได้ใช้เวลาของตัวประมวลผลไปแล้วน้อยที่สุด
- เลือกโปรเซสที่ได้ให้ผลลัพธ์ หรือเอาต์พุตออกมาแล้วน้อยที่สุด
- เลือกโปรเซสที่ได้ครอบครองทรัพยากรไปแล้วน้อยที่สุด
- เลือกโปรเซสที่มีลำดับความสำคัญ หรือ priority น้อยที่สุด
- เลือกโปรเซสที่ยังต้องการเวลาในการทำงานมากที่สุด
2.ทำการแทรกและเรียกทรัพยากรคืนจากกระบวนที่ละตัวจนกว่าจะวงจรอับจะหายไป การเลือกโปรเซสที่จะถูกแทรกมีหลักเกณฑ์เช่นเดียวกับข้อ 2 ส่วนโปรเซสที่ถูกแทรกจะต้องกลับไปเริ่มต้นใหม่ตั้งแต่จากเริ่มร้องขอทรัพยากรใหม่เลย
3.ยกเลิกการทำงานของทุกโปรเซสที่เกิดวงจรอับ (Abort ALL) ซึ่งเป็นหนึ่งในหลาย ๆ วิธีที่ระบบปฏิบัติทั่ว ๆ ไปใช้อยู่
4.ทำการสำรองข้อมูลของทุก ๆ โปรเซสที่เกิดวงจรอับไปยังจุดที่ทำการตรวจสอบก่อนหน้านี้ และให้โปรเซสทั้งหมดเริ่มทำงานใหม่ (Restart) อย่างไรก็ตาม การจะใช้วิธีการนี้ระบบจะต้องมีความสามารถในการย้อนกลับและเริ่มทำงานใหม่ได้ (Rollback and Restart) แต่ข้อด้อยของวิธีการนี้ก็คือ วงจรอับเดิมอาจจะเกิดขึ้นในระบบอีกก็ได้
4.7การที่ไม่ต้องสนใจอะไรเลย
วิธีการนี้ในต่างประเทศเรียกกันว่า วิธีการคิดแบบนกกระจองเทศ (Ostrich algorithm) ซึ่งมีความหมายมาจากลักษณะของนกกระจอกเทศที่เอาหัวมุดทรายและแกล้งทำเป็นไม่สนใจสิ่งที่เกิดขึ้น
ดังนั้นหลักการของวิธีการนี้ก็มีวิธีการใช้ของแต่ละคนที่ไม่เหมือนกัน นักคณิตศาสตร์อาจจะบอกว่าเขาไม่ยอมรับวธีการนี้ เพราะเขาต้องการป้องกันการเกิดวงจรอับ ถึงแม้ว่าจะต้องสูญเสียอะไรไปก็ตาม วิศวกรอาจถามปัญหาวงจรอับเกิดขึ้นบ่อยครั้งเพียงใด การที่ระบบล่มเพราะเหตุนี้บ่อยครั้งแค่ไหน และอาจจะทำให้เกิดความเสียหายรุนแรงมากหรือไม่ ถ้าวงจรอับเกิดขึ้นโดยเฉลี่ย1ครั้งในรอบ4ปีแต่ระบบกลับล่มเนื่องจาก ฮาร์ดแวร์เสีย การประมวลผลผิดพลาด ไวรัส และเกิดข้อผิดพลาดในตัวระบบปฏิบัติการเองทุกๆสัปดาห์ วิศวกรนั้นคงไม่มานั่งเสียเวลาในการจัดการกับการเกิดวงจรอับ การอธิบายข้อแตกต่างนี้ให้เห็นภาพชัดเจนได้นั้น ให้เราลองพิจารณาถึงระบบจริงๆ ที่อาจจะเกิดมีวงจรอับขึ้นมา แต่ไม่สามารถตรวจพบเจอได้เลยเป็นต้น
ระบบปฏิบัติการส่วนใหญ่ รวมทั้งUnix หรือ Windows นั้นจะไม่ค่อยสนใจปัญหาเหล่านี้มากนัก โดยเขาได้ตั้งสมมุติฐานเอาเองว่าผู้ใช้ หรือUser ส่วนใหญ่ต้องการให้เกิดวงจรอับขึ้นมาในระบบบ้าง เพื่อเป็นการห้ามไม่ให้ผู้ใช้หลายคนเรียกใช้โปรเซสเดียวกัน เปิดไฟล์เดียวกันหรือใช้อะไรอย่างดอย่างหนึ่งพร้อมกัน ถ้าการจัดการกับวงจรอับนั้นง่ายและระบบไม่ต้องสูญเสียอะไรมากนัก เราก็คงไม่ต้องกล่าวในรายละเอียด ร่วมถึงวิธีแก้ไขกันมาถึงเพียงนี้ แต่ปัญหาก็อยู่ที่ว่าสิ่งที่ต้องสูญเสียนั้นมีมาก โดยเฉพาะอย่างยิ่งข้อจำกัดต่างๆ ที่เกิดขึ้นกับโปรเซสที่จะต้องทำงาน และก็ทำให้เราต้องเผชิญอยู่กับสิ่งที่ไม่พึ่งปรารถนาระหว่างความถูกต้อง กับ ความสะดวกสบายและการพิจารณาว่าสิ่งใดนั้นสำคัญกว่ากัน ซึ่งการหาคำตอบที่มีเหตุผลของคำถามเหล่านี้คงเป็นไปแบบไม่ง่ายนัก
4.8สรุปวิธีการจัดการกับวงจรอับ
จากตารางที่4.2เป็นวิธีการจัดการกับวงจรอับแบบต่างๆ พร้อมทั้งแสดงถึงข้อดีและข้อเสียของแต่ละวิธี ในการออกแบบระบบปฏิบัติการนั้น เราควรนำวิธีการหลายๆวิธีมารวมกันเพื่อให้ระบบมีประสิทธิภาพในการจัดการกับเหตุการณ์ที่แตกต่างกันได้
เป็นที่ทราบกันดีว่า ไม่มีวิธีการใดวิธีเดียวที่จะเหมาะสมกับการจัดการปัญหาวงจรอับในระบบย่อยต่างๆของระบบปฏิบัติการได้ ไม่ว่าจะเป็น วิธีการป้องกัน วิธีการตรวจสอบและกู้คืน หรือวิธีการหลีกเลี่ยง เราจึงอาจต้องใช้หลายๆวิธีผสมกัน โดยเลือกวิธีที่เหมาะสมกับลักษณะของระบบย่อยนั้นๆ เราอาจเริ่มต้นได้จากการแบ่งทรัพยากรเป็ยพวกๆ และจัดเรียงตามความสำคัญ เพื่อที่เราจะได้ศึกษาหาวิธีการที่เหมาะสมที่สุดให้แต่ละกลุ่มของทรัพยากร ตัวอย่างของวิธีการแบ่งกลุ่มนั้น ให้เราพิจารณาระบบที่ประกอบไปด้วยกลุ่มของทรัพยากร 4 กลุ่มดังนี้
1.ทรัพยากรชั้นในของระบบ เป็นทรัพยากรที่ใช้โดยระบบ เช่นตัวควบคุมโปรเซส(Process control
block)
2.หน่วยความจำหลัก เป็นหน่วยความจำที่ใช้งานโดย ผู้ใช้
3.อุปกรณ์ต่างๆได้แก่อุปกรณ์ที่ต่อพ่วงเช่นCD-ROMไดว์หรืออุปกรณ์ทางตรรกเช่นไฟล์ก็ได้
4.หน่วยความจำสำรอง ได้แก่พื้นที่สำรองข้อมูลของผู้ใช้ในงานแต่ละคน เช่น ฮาร์ดดิกสก์
เราสามารถจัดการปัญหาวงจรอับในระบบนี้ โดยจัดแบ่งกลุ่มของทรัพยากรเป็น4กลุ่มตามที่กล่าวมาแล้วนั้น ในแต่ละกลุ่มอาจจะใช้วิธีจัดการดังนี้
1. ทรัพยากรชั้นในระบบ เราสามารถป้องกันได้โดยใช้การจัดลำดับของทรัพยากร เพราะโปรเซสที่ร้องขอเป็นโปรเซสภายในระบบของระบบเอง จึงต้องการให้ทรัพยากรกับระบบที่ร้องขอเร็วที่สุด
2. หน่วยความจำหลัก สามารถป้องกันโดยใช้วิธ๊แทรกกลางคันได้ เนื่องจากงานแต่ละงานแต่ละตัวสามารถย้ายออกจากหน่วยความจำหลัก เข้าไปเก็บไว้ในหน่วยความจำสำรองได้ง่าย
3. อุปกรณ์ต่างๆ สามารถป้องกันโดยใช้วิธีหลีกเลี่ยงได้ เพราะข้อมูลเกี่ยวกับ จำนวนทรัพยากรที่ร้องขอสูงสุดของแต่ละโปรเซสนั้น ระบบอาจจะรู้ล่วงหน้าได้ เช่น จากการ์ดควบคุมการทำงาน
4. หน่วยความจำสำรอง สามารถป้องกันได้โดยใช้วิธีการจัดสรรทรัพยากรไว้ล่วงหน้า เนื่องจากจำนวนหน่วยความจำสำรองสูงสุดของแต่ละงานมักจะถูกกำหนดไว้ล่วงหน้าอยู่แล้ว
จากตัวอย่างที่ได้กล่าวมา แสดงให้เห็นถึงแนวทางการจัดการกับปัญหาวงจรอับโดยใช้หลายๆวิธีผสมกันโดยเริ่มจากแบ่งกลุ่มของทรัพยากรออกเป็นพวกๆและเลือกหาวิธีที่เหมาะสมและส่งผลให้เกิดประสิทธิภาพสูงสุดให้กับงานแต่ละกลุ่ม


วิธีการจัดการ นโยบายการครอบครองทรัพยากร วิธีการจัดการแบบต่างๆ ข้อดี ข้อเสีย
การป้องกัน(Prevention) นโยบายค่อนข้างเข้มงวด เช่นจำกัดการใช้งานทรัพยากร •จัดลำดับการใช้งานทรัพยากร(Spooling)
•ให้โปรเซสร้องขอทรัพยากรทั้งหมดก่อนถึงเริ่มทำงาน
•การแทรกกลางคันได้ •ระบบไม่จำเป็นต้องจัดการขณะเครื่องทำงาน(run-time)เพราะปัญหาได้ถูกแก้เมื่อตอนออกแบบระบบแล้ว
•ทำงานได้ดีสำหรับโปรเซสที่มีการทำงานอย่างหนักเป็นช่วงๆ(bursting)
•เหมาะที่จะใช้กับทรัพยากรที่สามารถสำรองข้อมูลและกู้คืนได้ง่าย •ปฏิเสธการให้ทรัพยากรกับโปรเซส
•ไม่มีประสิทธิภาพ
•การทำงานของโปปรเซสเริ่มได้ช้าลง
•การแทรกกลางคันทำให้การทำงานไม่ต่อเนื่องและบางครั้งก็ไม่จำเป็น
การตรวจสอบและกู้คืน(Detection) นโยบายค่อนข้างเสรีทรัพยากรที่โปรเซสร้องขอสามารถได้รับได้เลย และค่อยทำการตรวจหาวงจรอับ •ทำการตรวจหาวงจรอับเป็นช่วงๆของเวลา •ไม่มีการชะลอเวลาเริ่มทำงานของโปรเซส
•เป็นเครื่องที่ใช้ในการจัดการแบบออนไลน์(online) •อาจจะมีการแทรกการทำงาน
•หรือโปรเซสต้องเริ่มทำงานใหม่ทั้งหมด
การหลีกเลี่ยง(Avoidance) เป็นนโยบายที่เป็นกลางระหว่างวิธีการทั้งสอง •พยายามทำให้ระบบอยู่ในสถานะปลอดภัย •ไม่มีการแทรกกลางคัน •จัต้องรู้จำนวนทรัพยากรที่ต้องการทั้งหมดก่อน
•โปรเซสอาจจะถูกปฏิเสธไม่ให้ทำงานเป็นเวลานานได้

ตารางที่ 4.2 สรุปวิธีการจัดการกับวงจรอับที่ใช้สำหรับระบบปฏิบัติการ
4.9สรุป
วงจรอับหรือ deadlock เป็นปัญหาที่สำคัญสำหรับทุกๆระบบปฏิบัติการ ปัญหานี้จะเกิดขึ้นเมื่อกลุ่มของโปรเซสหลายๆตัวต่างได้รับและกำลังถือครองทรัพยากร และโปรเซสแต่ละตัวเหล่านี้ต่างก้ต้องการใช้ทรัพยากรที่โปรเซสอื่นในกลุ่มนั้นครองอยู่ ดังนั้นโปรเซสาภายในกลุ่มนั้นจะถูกปฏิเสธให้ทำงาน(blocked)และไม่มีโปรเซสใดทำงานได้อีกต่อไป
ระบบปฏิบัติการสามารถหลีกเลี่ยง วงจรอับได้โดยตรวจสอบว่าระบบอยู่ในสถานะที่ปลอดภัยหรือไม่อย่างสม่ำเสมอ สถานะที่ปลอดภัยหรือ safe state คือสถานะที่ระบบสมารถทำการยืนยันได้ว่าโปรเซสต่างๆในระบบสามารถทำงานจนเสร็จสมบูรณ์ได้ แต่จะไม่สามารถทำการยืนยันได้ในสถานะที่ไม่ปลอดภัย และวิธีการคิดแบบนายธนาคาร (Banker’s algorithm) สามารถนำมาใช้ให้ระบบหลีกเลี่ยงการเกิดวงจรอับได้ โดยไม่อนุญาตให้ทรัพยากรแก่โปรเซสที่ร้องขอถ้าการให้นั้นจะทำให้ระบบเข้าไปอยู่ในสถานะที่ไม่ปลอดภัย
เราสามารถออกแบบระบบที่มีการป้องกันการเกิดวงจรอับตั้งแต่เริ่มต้นได้ ตัวอย่างเช่นการที่เราจะอนุญาตให้โปรเซสสามารถครอบครองทรัพยากรได้เพียง1ตัวในขณะหนึ่ง เพื่อเป็นการป้องกันการเกิดวงจรรอคอย(circuler wait) ซึ่งทำให้เกิดปัญหาวงจรอับอย่างแน่นอน หรือ วงจรอับสามารถป้องกันได้โดยใส่ลำดับเลขให้แก่ทรัพยากรทั้งหมด และให้โปรเซสร้องขอได้เฉพาะทรัพยากรที่มีลำดับของเลขสูงกว่าตัวเองถือครองอยู่