Khi CPU rảnh, lúc này CPU sẽ được cấp phát cho tiến trình ở đầu hàng đợi Tiến trình đang chạy sau đó sẽ bị xóa khỏi hàng đợi Nhược điểm: Thời gian chờ trung bình khá dài Giảm mức
Trang 1ĐẠI HỌC BÁCH KHOA HÀ NỘI
TRƯỜNG ĐIỆN – ĐIỆN TỬ
BÁO CÁO BÀI TẬP LỚN
HỆ ĐIỀU HÀNH
ĐỀ TÀI: Tìm hiểu và mô phỏng các thuật toán lập lịch
Giáo viên hướng dẫn:
Lớp:
Sinh viên thực hiện:
Nguyễn Thanh Bình 145603
Vũ Xuân Thịnh – 20203596 Đoàn Tiến Đạt - 20192746 Đoàn Tín Nhật - 20203525
Hà Nội,
Trang 2LỜI NÓI ĐẦU
Trang 3NỘI DUNG
Lời nói đầu 2
Chương 1 LÝ THUYẾT 4
1 CÁC KHÁI NIỆM CƠ BẢN 4
2 CÁC TIÊU CHUẨN CỦA CPU SCHEDULING 4
3 TỔNG QUAN VỀ LẬP LỊCH CPU CHO HỆ THỐNG SINGLE-PROCESSOR 4
3.1 First-Come, First-Served Scheduling (FCFS) 5
3.2 Shortest-Job-First Scheduling 5
3.3 Round-Robin Scheduling 5
3.4 Priority Scheduling 6
3.5 Multilevel Queue Scheduling 7
Chương 2 MÔ PHỎNG 8
1 MỤC TIÊU MÔ PHỎNG 8
2 XÂY DỰNG CÁC THUẬT TOÁN LẬP LỊCH 8
2.1 Xây dựng process ảo 8
2.2 Xây dựng các thuật toán lập lịch 9
2.2.1 First-come First-Serve (FCFS) 9
2.2.2 Shorteset-Job-First 11
2.2.3 Round-Robin 13
2.2.4 Priority scheduling 14
2.2.5 Multilevel queue scheduling 14
3 THIẾT KẾ GIAO DIỆN MÔ PHỎNG 15
3.1 Mục tiêu thiết kế 15
3.2 Ý tưởng và các bước thực hiện 15
Trang 4CHƯƠNG 1 LÝ THUYẾT
1 CÁC KHÁI NIỆM CƠ BẢN
CPU – I/O Burst Cycle (chu kỳ sử dụng CPU- I/O) : mô tả quá trình hoạt động của 1 tiến trình trong
hệ thống đa nhiệm (việc thực thi tiến trình bao gồm một chu kỳ thực thi CPU và chờ I/O)
Preemptive (trưng dụng) and Nonpreemptive (Không trưng dụng) Scheduling:
Non-preemptive: một tiến trình sẽ giữ CPU cho đến khi nó tự giải phóng CPU bằng cách hoàn thành công việc của mình hoặc chuyển sang trạng thái chờ đợi Các trường hợp bắt buộc chuyển đổi tiến trình chỉ xảy ra khi một tiến trình hoàn thành hoặc kết thúc
Preemptive: hệ điều hành có khả năng ngắt một tiến trình đang thực thi để cấp CPU cho một tiến trình khác Việc chuyển đổi tiến trình có thể xảy ra trong nhiều trường hợp, bao gồm khi một tiến trình hoàn thành I/O hoặc khi một tiến trình bị ngắt bởi một sự kiện như một hội tụ từ bên ngoài (interrupt)
Dispatcher (trình điều vận): Dispatcher là một thành phần trong hệ điều hành có nhiệm vụ quản lý việc chuyển đổi quyền điều khiển của CPU từ một tiến trình đang thực thi sang một tiến trình khác mà CPU Scheduler đã chọn Các nhiệm vụ của dispatcher:
Chuyển đổi ngữ cảnh
Chuyển đổi sang chế độ người dùng
Nhảy tới vị trí hợp lý trong chương trình người dùng để khởi động lại quá trình
2 CÁC TIÊU CHUẨN CỦA CPU SCHEDULING
CPU utilization (max): mục đích là làm CPU bận rộn nhất có thể Việc sử dụng CPU có thể từ 0 đến
100% Trong hệ thống thực, nó nên nằm trong khoảng từ 40% (cho hệ thống được nạp tải nhẹ) tới 90% (cho hệ thống được nạp tải nặng)
Throughput (max): số lượng quá trình được hoàn thành trên một đơn vị thời gian Đối với các quá
trình dài, tỉ lệ này có thể là 1 tiến trình/1 giờ; đối với các quá trình ngắn, throughput có thể là 10 tiến trình/1 giây
Turnaround time (min): Khoảng thời gian từ thời điểm gửi đến hệ thống tới khi tiến trình hoàn
thành Thời gian hoàn thành là tổng các thời gian chờ đưa quá trình vào bộ nhớ, chờ hàng đợi sẳn sàng, thực thi CPU và thực hiện I/O
Waiting time (min): là tổng thời gian chờ trong hàng đợi sẵn sàng
Response time (min): là thời gian hệ thống mất để bắt đầu đáp ứng yêu cầu sau khi nó được gửi Bao
gồm thời gian mà hệ thống tiêu tốn để đưa yêu cầu vào hàng đợi, chọn tiến trình để thực thi, và thực thi các công việc sơ bộ để chuẩn bị đáp ứng
3 TỔNG QUAN VỀ LẬP LỊCH CPU CHO HỆ THỐNG SINGLE-PROCESSOR Single-processor có nghĩa là chỉ chỉ có một lõi xử lý Do đó chỉ có một CPU với một lõi xử lý duy
nhất, do đó hệ thống chỉ có khả năng chạy một tiến trình tại một thời điểm
Trang 5Thuật toán phổ biến cho single-processors:
3.1 FIRST-COME, FIRST- SERVED SCHEDULING (FCFS)
Định nghĩa: Process nào yêu cầu CPU trước sẽ được cấp phát CPU trước
Cách làm việc: Việc triển khai FCFS có thể sử dụng một hàng đợi FIFO như sau:
Tiến trình được thêm vào hàng đợi sẵn sàng, PCB (Process Control Block) của nó được liên kết vào cuối hàng đợi
Khi CPU rảnh, lúc này CPU sẽ được cấp phát cho tiến trình ở đầu hàng đợi
Tiến trình đang chạy sau đó sẽ bị xóa khỏi hàng đợi
Nhược điểm:
Thời gian chờ trung bình khá dài
Giảm mức sử dụng CPU và thiết bị do không được ưu tiên cho quá trình sử dụng CPU trong thời gian ngắn
Non-preemptive
Ưu điểm:
Dễ thực hiện
3.2 SHORTEST-JOB-FIRST SCHEDULING
Định nghĩa: Quy trình có CPU-burst ngắn hơn sẽ có mức độ ưu tiên cao hơn
Cách làm việc:
Thuật toán liên kết với mỗi tiến trình theo độ dài của CPU Burst time tiếp theo của tiến trình
Khi CPU khả dụng, nó được gán cho tiến trình có CPU Burst tiếp theo nhỏ nhất
Nếu các CPU Burst tiếp theo của hai tiến trình giống nhau, thuật toán FCFS sẽ được sử dụng
Ưu điểm:
Thời gian chờ trung bình là tối thiểu cho một tập hợp các tiến trình đã cho
Có thể preemptive hoặc nonpreemptive
Nhược điểm:
Khó thực hiện được ở cấp độ lập lịch CPU, vì không có cách nào để biết độ dài chính xác của CPU Burst tiếp theo
CPU Burst tiếp theo thường được dự đoán là trung bình theo cấp số nhân của độ dài đo được của các đợt CPU trước đó, thuật toán rất phức tạp
3.3 ROUND-ROBIN SCHEDULING
Định nghĩa: Tương tự như FCFS, nhưng quyền ưu tiên được thêm vào để cho phép hệ thống chuyển
đổi giữa các tiến trình, mỗi tiến trình có một lượng quantum time được thực thi
Cách làm việc:
Trang 6 Time quantum thường nằm trong khoảng từ 10 đến 100 mili giây và hàng đợi được xem như một hàng đợi vòng
Tiến trình mới được thêm vào cuối của hàng đợi
Bộ lập lịch CPU chọn tiến trình đầu tiên từ hàng đợi sẵn sàng, đặt một bộ hẹn để ngắt sau 1 time quantum và execute tiến trình
Nếu tiến trình có chu kỳ CPU burst ít hơn 1 time quantum thì sẽ hoàn thành execution và tự giải phóng CPU => Bộ lập lịch chuyển sang tiến trình tiếp theo trong hàng đợi
Nếu chu kỳ CPU burst của tiến trình đang chạy dài hơn 1 time quantum, bộ đếm thời gian sẽ tắt và ngắt tiến trình đang chạy => Thông tin thực thi tiến trình sẽ được lưu lại và tiến trình sẽ được đưa vào cuối của hàng đợi => Bộ lập lịch CPU sẽ chọn tiến trình tiếp theo trong hàng đợi
Ưu điểm:
Đơn giản, dễ triển khai và không có tình trạng tiến trình đói (starvation) vì tất cả các tiến trình đều được chia sẻ CPU cách công bằng
Preemptive
Trong quá trình thực hiện lập lịch round-robin, time quantum có thể được cấp khác nhau cho các job khác nhau
Mỗi tiến trình có cơ hội được lập lịch lại sau một khoảng time quantum cụ thể
Nhược điểm:
Thời gian chờ đợi và thời gian phản hồi lớn
Mất thời gian cho quá trình chuyển đổi tiến trình
Lập kế hoạch tốn thời gian hơn nếu quantum nhỏ
3.4 PRIORITY SCHEDULING
Định nghĩa: Mức độ ưu tiên (priority) được liên kết với mỗi tiến trình và CPU sẽ được phân bổ cho
tiến trình có mức ưu tiên cao nhất
Ví dụ: FCFS là một loại lập lịch ưu tiên với mọi tiến trình có mức độ ưu tiên như nhau, SJF là một
loại lập lịch ưu tiên với các tiến trình có chu kỳ CPU dài hơn thì có mức ưu tiên thấp hơn
Cách làm việc: Vấn đề chính là làm thế nào để xác định mức độ ưu tiên:
Internally: sử dụng một số đại lượng có thể đo lường được để tính toán mức độ ưu tiên của một quy trình Ví dụ: giới hạn thời gian, yêu cầu bộ nhớ, số lượng tệp đang mở và tỷ lệ giữa số lượng I/O trung bình và số lượng CPU trung bình
Externally: các tiêu chí bên ngoài hệ điều hành, chẳng hạn như tầm quan trọng của quy trình, loại và số tiền được trả cho việc sử dụng máy tính, bộ phận tài trợ cho công việc và các yếu tố khác, thường là chính trị
Ưu điểm: Có thể Preemptive hoặc Nonpreemptive
Nhược điểm: Indefinite blocking or starvation: có thể khiến một số tiến trình có mức độ ưu tiên thấp
phải chờ vô thời hạn hoặc đói quá lâu
Một số giải pháp cho nhược điểm:
Trang 7 Tăng dần mức độ ưu tiên của các tiến trình chờ trong hệ thống trong thời gian dài
Kết hợp lập lịch round-robin và priority theo cách mà hệ thống thực thi quy trình có mức ưu tiên cao nhất và chạy các quy trình có cùng mức độ ưu tiên bằng cách sử dụng lập lịch round-robin
3.5 MULTILEVEL QUEUE SCHEDULING
Định nghĩa: Với lập lịch truyền thống: cả lập lịch priority và round-robin đều lưu trữ tất cả các quy
trình trong một hàng đợi duy nhất và bộ lập lịch sau đó chọn quy trình bằng cách tìm kiếm O(n) để xác định quy trình có mức ưu tiên cao nhất
Dễ dàng hơn: tách các hàng đợi cho từng mức độ ưu tiên riêng biệt và lập kế hoạch ưu tiên chỉ đơn giản là lên lịch cho quy trình trong hàng đợi có mức độ ưu tiên cao nhất
Cách làm việc:
Khi một tiến trình đến, nó sẽ được phân loại dựa trên đặc điểm của nó và được thêm vào một hàng đợi
Nếu có nhiều tiến trình trong hàng đợi có mức ưu tiên cao nhất, chúng sẽ được thực thi theo thứ tự round-robin
Trong dạng tổng quát nhất của phương pháp này, một ưu tiên được gán tĩnh cho mỗi tiến trình
và một tiến trình sẽ ở trong cùng một hàng đợi suốt thời gian chạy của nó
Mỗi hàng đợi có thể có thuật toán lập lịch riêng
Sẽ có sự lập lịch giữa các hàng đợi, thường được thực hiện dưới dạng lập lịch ưu tiên cố định
Có thể áp dụng phân chia thời gian giữa các hàng đợi: mỗi hàng đợi nhận được một phần thời gian CPU nhất định, sau đó nó có thể lập lịch giữa các tiến trình khác nhau của nó
Ưu điểm: Tính linh hoạt trong việc lập kế hoạch cho nhiều loại quy trình
Nhược điểm:
Sự phức tạp trong việc kiểm soát tất cả mức độ ưu tiên của hàng đợi và quy trình
Không cho phép tiến trình thay đổi hàng đợi
Trang 8CHƯƠNG 2 MÔ PHỎNG
1 MỤC TIÊU MÔ PHỎNG
Mô phỏng tất cả các thuật toán lập lịch cho CPU được đề cập trong phần lý thuyết:
First Come First Serve scheduling (FCFS)
Shortest-Job-First scheduling (SJF)
Round-Robin scheduling (RR)
Priority scheduling
Multilevel Queue scheduling
Đầu vào:
N processes ảo chứa đầy đủ thông tin để thuật toán lập lịch có thể quản lý process đó
Process bất kỳ được thêm vào trong thời gian thực khi chương trình mô phỏng đang chạy
Đầu ra:
Hiển thị trên giao diện quá trình các process ở ready queue và được thực thi ở CPU
Hiển thị trên giao diện Gant Chart các tiến trình được thực thi trong thời gian thực
Waiting time, Response time, Turn-around time của từng process và trung bình cho CPU utilization
Đánh giá: So sánh các thuật toán trên các test case dựa vào các thông số tiểu chuẩn của một
CPU Scheduler
2 XÂY DỰNG CÁC THUẬT TOÁN LẬP LỊCH
Ngôn ngữ lập trình: Python
Môi trường: Visual Studio Code
2.1 XÂY DỰNG PROCESS ẢO
Để phục vụ cho các thuật toán lập lịch và đánh giá kết quả của các thuật toán, một process ảo cần có các thành phần sau:
class Process():
def init (self, id:str, arrive_time:float, burst:float, priority:int) -> None:
self.id = id # ID của process sẽ là một sequence với chiều dài ID_LEN self.arrive_time = arrive_time #Thời gian tiến trình đến Queue
self.waiting_time = # Thời gian tiến trình wait trong queue
self.return_time = 0 # Return time của tiến trình
self.turnaround_time = 0 # Turnaround time của tiến trình
self.response_time = 0 # Response time của tiến trình
self.burst = burst # Burst CPU time của tiến trình
Trang 9self.priority = priority # Độ ưu tiên của tiến trình
self.completed = False # Trạng thái hoàn thành của tiến trình
2.2 XÂY DỰNG CÁC THUẬT TOÁN LẬP LỊCH
Test case sau được sử dụng để kiểm thử việc lập trình các thuật toán:
PID Arrive Time Burst Time Priority
Time quantum: 2 (Đối với các thuật toán cần time quantum)
2.2.1 First-come First-Serve (FCFS)
a) Mô hình thuật toán
b) Thực hiện thuật toán
- Khối “Sort process by arrival time”: Sử dụng thuật toán merge sort để sắp xếp thứ tự các process sẽ được thực thi
- Khối “Execute process” sẽ tính toán waiting time, response time, return time … của từng tiến trình và của tổng các tiến trình, có pseudocode như sau:
// Khởi tạo một biến để lưu tổng waiting time, turn around
time, response time, return time:
total_waiting_time <- 0
total_turnaround_time <- 0
total_response_time <- 0
total_return_time <- 0
P2: Arrive at
c
P1: Arrive at
b
P0: Arrive at
a
Sort process
by arrival time
Execute processe s
Trang 10// Cập nhật các process đã được sắp xếp theo arrive time
p <- Sorted processes array
len <- length of p
// Thực thi tiến trình đầu tiên:
p[0].return_time <- p[0].burst
p[0].turnaround_time <- p[0].return_time - p[0].arrive_time p[0].response_time <- 0
p[0].waiting_time <- 0
// cập nhật các tham số tổng thời gian
total_response_time <- total_response_time + p[0].response_time total_waiting_time <- total_waiting_time + p[0].waiting_time total_turnaround_time <- p[0].turnaround_time
total_return_time <- total_return_time + p[0].burst
// Tính toán các tiến trình còn lại
For i<-1 to len
// Tính toán các tham số thời gian cho từng tiến trình
p[i].waiting_time <- total_return_time - p[i].arrive_time p[i].return_time <- total_return_time + p[i].burst
p[i].turnaround_time <- p[i].return_time - p[i].arrive_time p[i].response_time <- p[i].waiting_time
// Cập nhật các thông số tổng thời gian xử lý:
total_return_time <- total_return_time + p[i].burst
total_waiting_time <- total_waiting_time + p[i].waiting_time total_turnaround_time <- p[i].turnaround_time
total_response_time <- p[i].response_time
EndFor
c) Kết quả kiểm thử thuật toán
Trang 112.2.2 Shorteset-Job-First
a) Mô hình thuật toán
b) Thực hiện thuật toán
// Khởi tạo biến để lưu tổng waiting time, turn around time, response time:
total_waiting_time <- 0
total_turnaround_time <- 0
total_response_time <- 0
// Cập nhật các process đã được sắp xếp theo burst time
p <- Sorted processes array
len-1 <- length of p
// Thực thi tiến trình đầu tiên:
curr_time <- 0
min_index <- 0
p[0].completed <- True
p[0].return_time <- p[0].burst
p[0].turnaround_time <- p[0].burst - p[0].arrive_time
P2: Arrive at
c
P1: Arrive at
b
P0: Arrive at
a
Sort processes
by burst
Execute processes
Trang 12p[0].waiting_time <- 0
curr_time <- p[0].burst
// Lặp qua từng tiến trình và chọn tiến trình có thời gian thực hiện nhỏ nhất tại thời điểm hiện tại
// cập nhật các tham số thời giane
p[min].waiting_time <- curr_time - p[min].arrive_time
p[min].completed <- True
curr_time <- curr_time + p[min].burst
p[min].return_time <- curr_time
p[min].turnaround_time <- p[min].return_time - p[min].arrive_time
// Tính toán các tiến trình còn lại
For i<-1 to len
// Tính toán các tham số thời gian cho từng tiến trình
p[i].return_time = p[i].turnaround_time + p[i].arrive_time p[i].response_time = p[i].waiting_time
// Cập nhật các thông số tổng thời gian xử lý:
total_waiting_time <- total_waiting_time + p[i].waiting_time total_turnaround_time <- p[i].turnaround_time
total_response_time <- p[i].response_time
EndFor
c) Kết quả kiểm thử thuật toán
Trang 132.2.3 Round-Robin
a) Sơ đồ thuật toán
b) Thực hiện thuật toán
c) Kết quả kiểm thử
2.2.4 Priority scheduling
a) Mô hình thuật toán
b) Thực hiện thuật toán
c) Kết quả kiểm thử
2.2.5 Multilevel queue scheduling
a) Mô hình thuật toán
b) Thực hiện thuật toán
c) Kết quả kiểm thử
1 Tìm hiểu lý thuyết và thuật toán Nhật
2 Lập trình các thuật toán Đạt, support: Thịnh, Nhật
3 THIẾT KẾ GIAO DIỆN MÔ PHỎNG
3.1 MỤC TIÊU THIẾT KẾ
- Giao diện cần thể hiện đầy đủ các yêu cầu sau của chương trình mô phỏng:
Có thanh Ready Queue chứa các process sẵn sàng
Có phần CPU thể hiện process nào đang được thực thi và phần trăm hoàn thành
Có Phần CPU Utilization thể hiện các thông số: Job – Hiện thị process đang được thực thi, Time – Hiển thị thời gian, Idle Time – Hiển thị tổng thời gian rỗi,
Avg.Waiting – Hiển thị thời gian chờ trung bình, Avg.Turnaround – Hiển thị thời gian turnaround trung bình
Có bảng tổng hợp kết quả của tất cả các process
Có chức năng thêm process bất kỳ vào ready queue trong thời gian thực
- Giao diện dễ nhìn, dễ hiểu
- Sử dụng ngôn ngữ Python và thư viện Pygame để thực hiện