Hệ điều hành (Part 4): CPU Scheduling

Ngày đăng: 2026-04-16

Lời mở đầu

Đây là bài viết tiếp theo nói về vấn đề lập lịch CPU trong hệ điều hành, đây là nhiệm vụ của bộ lập lịch ngắn hạn (Short-term Scheduler) đã được trình bày sơ lược trong phần trước.

Chủ yếu tìm hiểu về các lý thuyết về vấn đề này như các khái niệm, các tiêu chí và các thuật toán lập lịch CPU. Khuyến khích người đọc tự tìm hiểu cách các thuật toán chạy thông qua Youtube, bài viết tutorial,...

Ngoài ra còn có bộ điều phối tài nguyên Dispatcher sẽ thực hiện việc cấp CPU cho các tiến trình đã được CPU Scheduler chọn.

Dispatcher sẽ cần phải thực hiện context swtich Process, chuyển Process sang User-Mode và định vị vị trí của câu lệnh tiếp theo để Process thực hiện. Tất cả để đảm bảo Process này khi được cấp hoặc bị thu hồi CPU sẽ có thể tiếp tục các công việc dang dở của mình mà không bị lỗi. Việc này sẽ tốn một khoảng thời gian gọi là Dispatch latency.

Các khái niệm cơ bản

Mục đích của việc lập lịch CPU là để tận dụng tối đa CPU trong các hệ thống đa chương bằng cách chọn một trong các Process trong hàng đợi Ready và cấp CPU cho nó.

Ta có các thuật ngữ cơ bản trong lập lịch:

CPU Scheduler sẽ được gọi khi một Process:

Các Tiêu Chí Đánh Giá (Scheduling Criteria)

Trước khi tìm hiểu thuật toán, chúng ta cần nắm các tiêu chí dùng để đánh giá độ hiệu quả:

Các thuật toán lập lịch

1. Thuật toán Đến trước - Phục vụ trước (First-Come, First-Served - FCFS)

Cách hoạt động: Tiến trình nào yêu cầu CPU trước sẽ được cấp phát CPU trước. Thuật toán này là độc quyền (non-preemptive), nghĩa là hệ điều hành không thể thu hồi CPU giữa chừng cho đến khi tiến trình tự giải phóng.

Ưu điểm: Dễ hiểu và dễ cài đặt.

Nhược điểm: Hiệu suất kém do thời gian chờ trung bình thường cao. Nó có thể gây ra "Hiệu ứng đoàn tàu" (Convoy effect), tức là các tiến trình ngắn phải chờ rất lâu phía sau một tiến trình dài.

Ví dụ: Giả sử có 3 tiến trình đến cùng lúc theo thứ tự $P_1$, $P_2$, $P_3$ với thời gian chạy (Burst time) lần lượt là 24, 3, 3.

gantt title Biểu đồ Gantt - FCFS Scheduling dateFormat X axisFormat %s section Process 1 P1 (24ms) : 0, 24 section Process 2 P2 (3ms) : 24, 27 section Process 3 P3 (3ms) : 27, 30

2. Thuật toán Công việc ngắn nhất (Shortest-Job-First - SJF)

Cách hoạt động: Gắn mỗi tiến trình với thời gian chạy tiếp theo của nó, thuật toán sẽ chọn tiến trình có thời gian chạy ngắn nhất để thực thi trước.

Đặc điểm: SJF là thuật toán tối ưu vì nó mang lại thời gian chờ trung bình nhỏ nhất cho một tập hợp các tiến trình.

Phân loại: * Không độc quyền (Non-preemptive): Khi CPU đã cấp cho tiến trình, nó không bị thu hồi cho đến khi chạy xong. * Độc quyền (Preemptive - hay còn gọi là SRTF): Nếu một tiến trình mới xuất hiện có thời gian chạy ngắn hơn thời gian chạy còn lại của tiến trình đang thực thi, CPU sẽ bị thu hồi và chuyển sang tiến trình mới.

Ví dụ (Preemptive SJF): Các tiến trình đến với Thời gian đến / Thời gian chạy tương ứng:

$P_1$ (0.0 / 7), $P_2$ (2.0 / 4), $P_3$ (4.0 / 1), $P_4$ (5.0 / 4).

gantt title Biểu đồ Gantt - SJF (Không độc quyền) dateFormat X axisFormat %s section Process 1 P1 (7ms) : 0, 7 section Process 2 P2 (4ms) : 8, 12 section Process 3 P3 (1ms) : 7, 8 section Process 4 P4 (4ms) : 12, 16
gantt title Biểu đồ Gantt - Preemptive SJF (SRTF) dateFormat X axisFormat %s section Process 1 P1 (2ms) : 0, 2 P1 (5ms) : 11, 16 section Process 2 P2 (2ms) : 2, 4 P2 (2ms) : 5, 7 section Process 3 P3 (1ms) : 4, 5 section Process 4 P4 (4ms) : 7, 11

3. Thuật toán theo độ ưu tiên (Priority Scheduling)

Cách hoạt động: Mỗi tiến trình được gắn một số nguyên thể hiện độ ưu tiên (thông thường số càng nhỏ thì độ ưu tiên càng cao). Tiến trình có độ ưu tiên cao nhất sẽ được cấp CPU. Bản thân SJF cũng là một dạng lập lịch ưu tiên, trong đó độ ưu tiên chính là thời gian chạy ngắn nhất.

Vấn đề: Gây ra tình trạng "Đói tài nguyên" (Starvation) - các tiến trình có độ ưu tiên thấp có thể không bao giờ được thực thi.

Giải pháp: Sử dụng cơ chế "Lão hóa" (Aging), nghĩa là theo thời gian, hệ thống sẽ tự động tăng dần độ ưu tiên của các tiến trình đang chờ để đảm bảo cuối cùng chúng cũng được chạy.

Ví dụ: 5 tiến trình đến cùng lúc. (Độ ưu tiên: Số càng nhỏ càng ưu tiên).

gantt title Biểu đồ Gantt - Priority Scheduling dateFormat X axisFormat %s section P2 (Pri 1) P2 (1ms) : 0, 1 section P5 (Pri 2) P5 (5ms) : 1, 6 section P1 (Pri 3) P1 (10ms): 6, 16 section P3 (Pri 4) P3 (2ms) : 16, 18 section P4 (Pri 5) P4 (1ms) : 18, 19

4. Thuật toán Quay vòng (Round Robin - RR)

Cách hoạt động: Mỗi tiến trình được cấp một lượng thời gian CPU nhỏ gọi là "time quantum" (thường từ 10-100 ms). Sau khi hết khoảng thời gian này, tiến trình bị thu hồi CPU và đẩy xuống cuối hàng đợi ready. Thuật toán này giúp không tiến trình nào bị đói tài nguyên.

Hiệu năng: * Nếu time quantum quá lớn, RR sẽ trở thành thuật toán FCFS.

Nếu time quantum quá nhỏ, số lần chuyển đổi ngữ cảnh (context switch) sẽ tăng cao gây lãng phí thời gian hệ thống.

Ví dụ: 4 tiến trình đến cùng lúc tại thời điểm 0 với Thời gian chạy: $P_1$ (53), $P_2$ (17), $P_3$ (68), $P_4$ (24). Time Quantum = 20.

gantt title Biểu đồ Gantt - Round Robin (Quantum = 20) dateFormat X axisFormat %s section Process 1 P1 (20) : 0, 20 P1 (20) : 77, 97 P1 (13) : 121, 134 section Process 2 P2 (17) : 20, 37 section Process 3 P3 (20) : 37, 57 P3 (20) : 97, 117 P3 (20) : 134, 154 P3 (8) : 154, 162 section Process 4 P4 (20) : 57, 77 P4 (4) : 117, 121

5. Hàng đợi đa mức (Multilevel Queue) & Hồi tiếp (Multilevel Feedback Queue)

Multilevel Queue: Hàng đợi ready được chia thành các hàng đợi riêng biệt (ví dụ: foreground cho tương tác và background cho xử lý ngầm). Mỗi hàng đợi có thuật toán lập lịch riêng (như RR cho foreground và FCFS cho background). Mỗi tiến trình chỉ thuộc cố định một hàng đợi.

Ví dụ: Để dễ hình dung thuật toán này, ta theo dõi chỉ 1 tiến trình P1 có thời gian chạy là 30ms.

Hệ thống có 3 hàng đợi: Q0 (RR q=8), Q1 (RR q=16), Q2 (FCFS).

Kết quả: P1 bị đẩy dần xuống các hàng đợi ưu tiên thấp hơn khi nó tiêu thụ hết time quantum.

gantt title Multilevel Feedback Queue (Theo dõi Process 1 - Burst 30ms) dateFormat X axisFormat %s section Queue 0 (RR q=8) P1 chạy 8ms rồi bị giáng cấp : 0, 8 section Queue 1 (RR q=16) P1 chạy tiếp 16ms rồi giáng cấp : 8, 24 section Queue 2 (FCFS) P1 chạy 6ms còn lại đến khi xong : 24, 30

Tài liệu tham khảo


← Quay lại trang chủ