Một vấn đề quan trọng đối với hệ điều hành là chọn khung nào trong các khung không bị khoá để tiến hành đổi trang. Chiến lược lựa chọn thích hợp cho phép tối ưu một số tham số, trong đó quan trọng nhất là giảm tần suất đổi trang. Chiến lược đổi trang tốt là chiến lược cho phép giảm số lần đổi trang, trong khi có tốc độ nhanh và dễ triển khai. Các chiến lược đổi trang đã được đề xuất và khảo sát trong rất nhiều nghiên cứu về quản lý bộ nhớ. Trong phần này, một số chiến lược đổi trang sẽ được trình bày và phân tích.
Các chiến lược đổi trang được trình bày trong phần này bao gồm: - Đổi trang tối ưu( OPT)
- Đổi trang theo nguyên tắc FIFO - Trang ít được dùng nhất (LRU) - Chiến lược đồng hồ (CLOCK)
a. Đổi trang tối ưu (OPT)
Với chiến lược này, hệ điều hành chọn trang nhớ sẽ không được dùng tới trong khoảng thời gian lâu nhất để trao đổi. Nói cách khác, trang bị đổi là trang có lần truy cập tiếp theo cách xa thời điểm hiện tại nhất. Chiến lược này cho phép giảm tối thiểu sự kiện thiếu trang và do đó là tối ưu theo tiêu chuẩn này. Tuy nhiên, để sử dụng chiến lược này, hệ điều hành cần đoán trước nhu cầu sử dụng các trang trong tương lai. Điều này rất khó thực hiện trên thực tế do thứ tự truy cập trang không cố định và không biết trước. Chiến lược đổi trang tối ưu, do đó, không thể áp dụng trong thực tế mà chỉ được dùng để so sánh với các chiến lược đổi trang khác.
Các chiến lược đổi trang được minh họa qua ví dụ sau. Giả sử tiến trình được cấp 3 khung, không gian nhớ logic của tiến trình gồm 5 trang và các trang của tiến trình được truy cập theo thứ tự sau: 2, 3, 2, 1, 5, 2, 4, 5, 3, 2, 5, 2.
Thứ tự đổi trang khi sử dụng phương pháp đổi trang tối ưu được minh họa trên hình sau, trong đó F ký hiệu cho tình huống thiếu trang gây ra đổi trang mới. Trước tiên, các khung nhớ đều trống. Việc truy cập các trang 2, 3, 1 sẽ tới việc nạp các trang này vào ba khung nhớ trống. Khi truy cập trang số 5 không còn khung nhớ trống và do vậy phải đổi trang. Trong số ba trang 2, 3, 1 đang ở trong bộ nhớ, trang số 1 sau đó không được sử dụng, tức là có thời điểm sử dụng trong tương lai xa hiện tại nhất nên bị đổi ra đĩa. Tiếp theo, khi truy cập trang số 4 sẽ gây đổi trang tiếp theo. Trong số ba trang 2, 3, 5 trang 2 có lần truy cập tiếp theo muộn hơn so với trang 3 và 5, do vậy bị đổi ra. Theo cách thực hiện như trên, ta có thứ tự truy cập và đổi các trang còn lại diễn ra như trên hình vẽ.
Đổi trang tối ưu đòi hỏi 3 lần đổi trang cho chuỗi truy cập trên.
2 3 2 3 2 3 1 F 2 3 5 2 3 5 F 4 3 5 4 3 5 4 3 5 2 3 5 F 2 3 5 2 3 5 2 OPT 2 3 2 1 5 2 4 5 3 2 5 2
b. Vào trước, ra trước (FIFO)
Đây là chiến lược đơn giản nhất. Trang được đọc vào bộ nhớ trước sẽ bị đổi ra trước khi có yêu cầu đổi trang. Chiến lược này có thể triển khai một cách đơn giản bằng cách sử dụng hàng đợi FIFO. Khi trang được nạp vào bộ nhớ, số thứ tự trang được thêm vào cuối hàng đợi. Khi cần đổi trang, trang có số thứ tự ở đầu hàng đợi sẽ bị đổi.
Ngoài đặc điểm đơn giản, chiến lược FIFO dựa trên giả thiết sau: trang bị trao đổi là trang nằm trong bộ nhớ lâu nhất. Do nằm trong bộ nhớ lâu nhất nên có nhiều khả năng trang đó không còn cần tới nữa. Rõ ràng, lôgic này là không đúng trong nhiều trường hợp. Có những phần lệnh và dữ liệu của chương trình được dùng rất nhiều trong suốt quá trình tồn tại của tiến trình, chẳng hạn một số biến toàn cục được truy cập nhiều trong suốt vòng đời tiến trình. Vì vậy, chiến lược FIFO thường gây ra tần suất đổi trang lớn so với các chiến lược đổi trang khác.
Kết quả đổi trang sử dụng FIFO cho chuỗi truy cập ở ví dụ trên được minh họa trên hình sau. Khi truy cập trang số 5, trong bộ nhớ đang có các trang 2, 3, 1, trong đó trang số 2 được nạp vào bộ nhớ sớm nhất và do vậy bị đổi. Tiếp theo, khi truy cập trang số 2, trong ba trang 5, 3, 1, trang 3 được nạp vào sớm nhất và do vậy bị đổi ra để nhường chỗ cho trang số 2. Kết quả, với ví dụ đã cho, chiến lược đổi trang FIFO gây ra sáu lần đổi trang, nhiều hơn đáng kể so với đổi trang tối ưu ở trên.
2 2 3 2 3 2 3 1 5 3 1 5 2 1 5 2 4 5 2 4 F F F F 3 2 4 3 2 4 3 5 4 3 5 2 F F FIFO 2 3 2 1 5 2 4 5 3 2 5 2
c. Đổi trang ít sử dụng nhất trong thời gian cuối LRU (Least Recently Used)
Ở chiến lược đổi trang này, trang bị đổi là trang mà thời gian từ lần truy cập cuối cùng đến thời điểm hiện tại là lâu nhất. Nói cách khác, đó là trang ít được truy cập trong thời gian
cuối nhất trong số các trang đang nằm trong bộ nhớ.
Chiến lược đổi trang LRU dựa trên nguyên tắc cục bộ về thời gian, theo đó trang đang được sử dụng sẽ được sử dụng tiếp. Ngược lại trang ít được sử dụng hiện tại sẽ ít khả năng được sử dụng tới trong tương lai gần và do vậy cần được đổi ra nhường chỗ cho trang mới.
Phương pháp này ngược với phương pháp đổi trang tối ưu. Với đổi trang tối ưu, tiêu chí để chọn trang là thời gian truy cập trang trong tương lai. Trong khi đó, ở đây, thời gian được sử dụng làm tiêu chí so sánh là khoảng thời gian không sử dụng trang trong quá khứ. Thực tế cho thấy, LRU cho kết quả tốt gần như phương pháp đổi trang tối ưu.
Với ví dụ chuỗi truy cập trang ở trên, LFU cho kết quả đổi trang như sau:
2 2 3 2 3 2 3 1 2 5 1 F 2 5 1 2 5 4 2 5 4 F 3 5 4 F F 3 5 2 3 5 2 3 5 2 LRU 2 3 2 1 5 2 4 5 3 2 5 2
Khi đổi cần chọn trang để đổi khi truy cập trang số 5 lần đầu tiên, trong số ba trang 2, 3, 1, trang 1 vừa được truy cập xong, trước đó là trang 2, trước nữa mới là trang 3. Như vậy trang 3 là trang có lần truy cập cuối xa hiện tại nhất và do vậy bị đổi. Khi truy cập tới trang 4 lại cần đổi trang: trong số ba trang 2, 5, 1, trang 2 được truy cập ngay trước đó, trước nữa là trang 5 và xa nhất là trang 1, do vậy trang 1 bị đổi nhường chỗ cho trang 4. Kết quả, với ví dụ trên, phương pháp LRU gây ra bốn lần đổi trang, chỉ nhiều hơn một lần so với đổi trang tối ưu OPT.
Mặc dù có hiệu quả tốt do ít gây ra đổi trang, việc triển khai LRU tương đối khó khăn, chậm hơn hơn so với phương pháp FIFO và thường đòi hỏi sự hỗ trợ của phần cứng để đảm bảo về tốc độ. Khó khăn chính ở đây là làm sao xác định được trang có lần truy cập cuối diễn ra cách thời điểm hiện tại lâu nhất. Sau đây là hai cách giải quyết:
- Sử dụng biến đếm: mỗi khoản mục của bảng phân trang sẽ có thêm một trường chứa thời gian truy cập trang lần cuối. Đây không phải thời gian thực mà là thời gian lôgic do hệ thống xác định như sau. CPU có thêm một thanh ghi chứa một số đếm, số đếm này chính là thời gian lôgic. Chỉ số của số đếm tăng mỗi khi xảy ra truy cập bộ nhớ. Mỗi khi một trang nhớ được truy cập, nội dung của số đếm sẽ được ghi vàko trường thời gian truy cập trong khoản mục của trang đó, sau đó số đếm tăng lên một đơn vị. Như vậy trường này luôn chứa thời gian truy cập trang lần cuối. Trang bị đổi sẽ là trang có giá trị trường này nhỏ nhất. Như vậy mỗi khi có yêu cầu đổi trang, hệ điều hành sẽ tìm trong bảng phân trang để xác định trang có tuổi bé nhất. Cách triển khai này đòi hỏi có sự tham gia của phần cứng.
- Sử dụng hàng đợi đặc biệt: một hàng đợi được sử dụng để chứa số thứ tự trang. Khi trang được đọc vào bộ nhớ, số thứ tự trang được thêm vào cuối hàng đợi. Mỗi khi một trang nhớ được truy cập, số thứ tự trang sẽ được chuyển về cuối hàng đợi. Như vậy cuối hàng đợi sẽ chứa trang được truy cập gần đây nhất, trong khi đầu hàng đợi chính là trang LRU, tức là trang cần trao đổi. Lưu ý, hàng đợi ở đây là hàng đợi đặc biệt trong đó các phần tử có thể lấy ra từ vị trí bất kỳ chứ không nhất thiết từ đầu, do vậy không giống với hàng đợi truyền
thống. Mặc dù việc tìm kiếm và chuyển vị trí số trang trong hàng đợi đòi hỏi một số thời gian xong ta lại tránh được việc tìm kiếm trong bảng phân trang. Phương pháp này thích hợp cho việc thực hiện bằng phần mềm.
d. Thuật toán đồng hồ
Thuật toán đồng hồ (clock), còn gọi là thuật toán cơ hội thứ hai (second chance), là một cải tiến của thuật toán FIFO nhằm tránh thay thế những trang mặc dù đã được nạp vào lâu nhưng hiện vẫn có khả năng được sử dụng. Khi chọn trang, thuật toán đồng hồ dựa trên hai thông tin. Thứ nhất, đó là thứ tự nạp trang vào bộ nhớ. Thứ hai, thông tin về việc gần đây trang có được truy cập hay không.
Thuật toán đồng hồ được thực hiện như sau. Mỗi trang được gắn thêm một bit gọi là bit sử dụng, ký hiệu là U, chứa trong bảng phân trang. Mỗi khi trang được truy cập để đọc hoặc ghi, bit U của trang đó được đặt giá trị bằng 1. Như vậy, ngay khi trang được đọc vào bộ nhớ, bit U của trang đã được đặt bằng 1.
Các khung có thể bị đổi, hay trang tương ứng, được liên kết vào một danh sách vòng, tức là danh sách có đầu và cuối trùng nhau. Danh sách này có một con trỏ có thể chuyển động theo một chiều nhất định để trỏ lần lượt vào các trang trong danh sách. Khi một trang nào đó bị đổi, con trỏ được dịch chuyển để trỏ vào trang tiếp theo trong danh sách. Danh sách có thể thể hiện tương tự như một mặt đồng hồ với các khung/trang là con số và và con trỏ là kim đồng hồ chuyển động theo một chiều nhất định (hình 3.18).
Trang 1 U = 1 Trang 45 U = 1 Trang 191 U = 1 Trang 556 U = 0 Trang 13 U = 0 Trang 67 U = 1 Trang 33 U = 1 Trang 222 U = 0 Con trỏ tới khung tiếp theo 0 1 2 3 4 5 6 7 8 Trang 9 U = 1 Trang 19U = 1 n - 1
Khung đâu tiên thích hợp cho thay thế
Hình 3.18 .Thuật toán đồng hồ
Khi có nhu cầu đổi trang, hệ điều hành kiểm tra trang đang bị trỏ tới. Nếu bit U của trang bằng 0, trang sẽ bị đổi ngay. Ngược lại, nếu bit U bằng 1, hệ điều hành sẽ đặt bit U bằng 0, chuyển sang trang tiếp theo trong danh sách và lặp lại thủ tục trên.
Với cách thực hiện như trên, nếu tại thời điểm đổi trang bit U của tất cả trang trong danh sách bằng 1 thì con trỏ sẽ quay đúng một vòng, đặt bit U của tất cả trang bằng 0, sau đó trang hiện thời đang bị trỏ tới sẽ bị đổi.
Minh họa cho hoạt động của thuật toán đồng hồ: với ví dụ chuỗi truy cập trang nhớ được cho ở trên, ta có kết quả đổi trang như thể hiện trên hình dưới. Trên hình vẽ, vị trí con trỏ được thể hiện bằng mũi tên trỏ vào trang tương ứng. Dấu sao ‘*’ bên cạnh số thứ tự trang tương ứng với giá trị bit U = 1, các trang với U = 0 không có dấu ‘*’. Khi nạp các trang đầu tiên, sau mỗi lần nạp trang con trỏ được chuyển sang trang tiếp theo trong danh sách vòng. Khi truy cập trang 5 lần đầu và cần tìm trang để đổi, con trỏ đang ở vị trí trang số 2 và cả ba trang 2, 3, 1 đều có U = 1, do vậy con trỏ sẽ di chuyển đúng một vòng, xóa các bit U về 0, quay lại vị trí cũ và do vậy trang số 2 bị đổi. Sau đó, con trỏ di chuyển sang trang tiếp theo là trang số 3. Tiếp theo, khi truy cập trang số 2, trang đang bị trỏ vào là trang số 3 có U = 0 do vậy trang này bị đổi ra ngoài. Quá trình này được tiếp tục. Một điểm cần lưu ý là khi truy cập trang số 2 ở trạng thái thứ 10 (trạng thái thứ 3 tính từ cuối lên), do trang số 2 đã có trong bộ nhớ, thuật toán không tiến hành đổi trang nhưng đặt bit U của trang 2 thành U = 1, nhờ vậy mà trang số 2 không bị đổi trong lần đổi trang tiếp theo. Trên ví dụ đang sử dụng, thuật toán đồng hồ gây ra 5 lần đổi trang, tốt hơn so với FIFO mặc dù vẫn nhiều hơn so với LRU.
3* 2 4 3* 2 5* 3* 2* 5* 3* 2* 4 5* 2* 4* 5* 2* 4* 5* 2* 1 5* 3 1 2* 3* 1* 2* 2* 3* 2* 3* F F F F F CLOCK 2 3 2 1 5 2 4 5 3 2 5 2
So với FIFO, thuật toán đồng hồ căn cứ trên hai thông tin để đưa ra quyết định đổi trang. Thông tin thứ nhất là thời gian trang được tải vào, thể hiện qua vị trí trang trong danh sách tương tự như FIFO. Thông tin thứ hai là việc gần đây trang có được sử dụng không, thể hiện qua nội dung bit U. Việc kiểm tra thêm bit U tương tự việc cho trang thêm khả năng được giữ trong bộ nhớ và vì vậy thuật toán có tên gọi khác là “cơ hội thứ hai”.
e. Thuật toán đồng hồ cải tiến
Một số biến thể của thuật toán đồng hồ có thể sử dụng để tận dụng thêm thông tin phụ giúp cho việc đổi trang được tốt hơn. Chẳng hạn, ngoài bit U, thuật toán đồng hồ có thể sử dụng thêm thông tin về việc nội dung trang có bị thay đổi không. Trong một phần trước, ta đã biết rằng nếu nội dung trang bị thay đổi sau khi nạp vào thì khi đổi trang sẽ mất thời gian hơn do phải ghi nội dung trang ra đĩa. Để đánh dấu những trang có nội dung thay đổi, hệ thống sử dụng bit M, với M được đặt bằng 1 mỗi khi ghi vào trang.
Kết hợp bit U và bit M, ta có bốn khả năng sau:
- U=0, M=0: cho thấy trang gần đây không được truy cập và nội dung cũng không bị thay đổi, rất thích hợp để bị đổi ra ngoài.
- U=0, M=1: trang có nội dung thay đổi nhưng gần đây không được truy cập, cũng là ứng viên để đổi ra ngoài mặc dù đòi hỏi thời gian ghi ra đĩa so với trường hợp trên. - U=1, M=0: trang mới được truy cập gần đây và do vậy theo nguyên lý cục bộ về
thời gian có thể sắp được truy cập tiếp.
- U=1, M=1: trang có nội dung bị thay đổi và mới được truy cập gần đây, chưa thật thích hợp để đổi.
Có thể nhận thấy, đi từ trên xuống dưới, những trường hợp phía trên nên đổi trước trường hợp phía dưới.
Để đổi trang theo thứ tự liệt kê ở trên, thuật toán đồng hồ cải tiến thực hiện các bước sau:
Bước 1: Bắt đầu từ vị trí hiện tại của con trỏ, kiểm tra các trang. Trang đầu tiên có U=0 và M=0 sẽ bị đổi. Ở bước này, thuật toán chỉ kiểm tra mà không thay đổi nội dung bit U, bit M.
Bước 2: Nếu quay hết một vòng mà không tìm được trang có U=0 và M=0 thì quét lại danh sách lần hai. Trang đầu tiên có U=0 và M=1 sẽ bị đổi. Trong quá trình