1 B ng t ng kả ổ ết các hàm được thêm mới và các hàm được sửa đổi trong vấn đề “Priority Scheduling” .... CHƯƠNG 2: DỰ ÁN LUỒNG – VẤN ĐỀ “PRIORITY SCHEDULING”2.1 C u trúc dấ ữ liệ u và
Trang 1VIỆN ĐIỆN TỬ - VIỄ N THÔNG
BÁO CÁO BÀI T P L N MÔN H Ậ Ớ Ệ ĐIỀ U HÀNH
ĐỀ TÀI:
DONATION” TRONG D ÁN S 1 C A H Ự Ố Ủ Ệ ĐIỀU HÀNH
PINTOS
Phạm Qu c Trung ố 20172875 119074
Giảng viên hướ ng dẫn: TS Ph ạm Văn Tiế n
HÀ NỘI 12/2020
Trang 2DANH MỤC HÌNH ẢNH 1
DANH M C BỤ ẢNG BIỂU 1
CHƯƠNG 1: HỆ ĐIỀU HÀNH PINTOS 2
1.1 T ng quan v Pintosổ ề 2
2.1 H ệ thống thư mụ c c a hủ ệ điề u hành Pintos 2
CHƯƠNG 2: DỰ ÁN LUỒNG – VẤN ĐỀ “PRIORITY SCHEDULING” 5
2.1 C u trúc d u và các hàm quan trấ ữ liệ ọng 5
2.1.1 C u trúc semaphoreấ 5
2.1.2 C u trúc lockấ 5
2.1.3 C u trúc condition variableấ 6
2.2 Vấn đề đặ t ra 7
2.3 M c tiêu cụ ủa đề tài 8
2.4 Phương án giải quyết 8
2.4 Tri n khai cể ụ thể 10
CHƯƠNG 3: DỰ ÁN LUỒNG – VẤN ĐỀ “PRIORITY DONATION” 11
3.1 Các c u trúc dấ ữ liệ u quan tr ọng 11
3.2 Vấn đề đặ t ra 11
3.3 M c tiêu cụ ủa đề tài 12
3.4 Phương án giải quyết 12
3.4 Tri n khai cể ụ thể 14
CHƯƠNG 4: KẾT QUẢ 17
4.1 K t qu sau khi chế ả ạy “make check” 17
4.2 Kết luận 17
Trang 3DANH MỤC HÌNH ẢNH
Hình 2 1 Cơ chế Round - Robin 7
Hình 2 2 Cơ chế Priority Scheduling 9
Hình 3 1 Vấn đề “Priority Inversion” 11
Hình 3 2 Ý tưởng thực hiện “Priority Donation” 12
Hình 3 3 Vấn đề Multiple Donation gi a các lu ng 13 ữ ồ Hình 3 4 Vấn đề Nested Donation gi a các lu ng 14 ữ ồ Hình 3 5 Ý tưởng cho vấn đề Multiple Donation 15
Hình 3 6 Ý tưởng cho vấn đề Nested Donation 15
Hình 4 1 Kết quả khi ch y make check 17ạ DANH M C B NG BI U Ụ Ả Ể Bảng 2 1 B ng t ng kả ổ ết các hàm được thêm mới và các hàm được sửa đổi trong vấn đề “Priority Scheduling” 10
Bảng 3 1 B ng t ng kả ổ ết các hàm được thêm mới và các hàm được sửa đổi trong vấn đề “Priority Inversion” 16
Trang 4CHƯƠNG 1: HỆ ĐIỀU HÀNH PINTOS
1.1 T ng quan v Pintos ổ ề
Hệ điều hành Pintos là m t hộ ệ điều hành đơn giản ch y trên n n ki n trúc 80x86 H ạ ề ế ệ điều hành này được nghiên cứu và phát triển bởi đại học Stanford với mục đích chính để phục v cho quá trình h c t p và nghiên c u c a sinh viên Nó có h ụ ọ ậ ứ ủ ỗ trợ các cơ chế cơ bản của m t hộ ệ điều hành như luồng kernel, tải nạp và chạy các chương trình người dùng, hệ thống filesystem,… Tuy vậy các cơ chế này được triển khai khá đơn giản và còn nhi u v n ề ấ
đề cần khắc phục
Dựa trên tình hình th c t , 4 dự ế ự án Pintos được đưa ra để kh c ph c ph n nào nh ng ắ ụ ầ ữ vấn đề nêu trên Các dự án này chủ yếu xoay quanh một số nội dung như thread (luồng), user program (chương trình người dùng), virtual memory (bộ nhớ ảo) và filesystem (hệ thống file) Sau khi triển khai được các n i dung này, h ộ ệ điều hành s hoẽ ạt động hi u quệ ả, nâng cao hi u su t c a h ệ ấ ủ ệ thống cũng như tiết kiệm được các tài nguyên vốn dĩ có hạn như thời gian, năng lư ng, bộ nh ợ ớ
Các d án c a Pintos s ự ủ ẽ được ch y và ki m tra b ng m t h ạ ể ằ ộ ệ thống mô ph ng B n ch t, ỏ ả ấ
nó cũng chính là một chương trình với chức năng mô phỏng lại một hệ vi xử lý kiến trúc 80x86 cũng như các ngoại vi của nó sao cho vừa đủ để các chương trình của Pintos có thể chạy được trên nó Hai chương trình mô phỏng phổ biến nhất là Boshs và QEMU Trong báo cáo cũng như dự án này sẽ sử dụng trình mô phỏng QEMU
2.1 H ệ thống thư mụ c c a h ủ ệ điều hành Pintos
Bên trong mã ngu n Pintos, chúng ta có th nh n ra m t sồ ể ậ ộ ố thư mục, các dự án Pintos sẽ được triển khai trên các thư mục này Chúng ta có th tìm thể ấy các thư mục theo đường dẫn sau “…/pintos/src”
Thư mục “luồngs/”
Đây là nơi chứa mã nguồn của kernel gốc Nó cũng là nơi mà chúng ta sẽ triển khai
dự án 1 “Luồng”
Thư mục “userpro/”
Trang 5Thư mục ch a mã ngu n cho trình t i n p ứ ồ ả ạ ứng dụng người dùng Đây sẽ là nơi chúng
ta triển khai d ự án 2 “User Program”
Thư mục “vm/”
Đây gần như là một thư mục rỗng Nó sẽ là nơi chúng ta triển khai n i dung liên ộ quan đến dự án số 3 “Virtual Memory”
Thư mục “filesys/”
Thư mục chứa mã nguồn cho hệ thống file cơ bản Thư mục này sẽ được s d ng ử ụ trong cả 2 d án là d án vự ự ề “User Program” và dự án về “File System”
Thư mục “devices/”
Đây là thư mục chứa mã nguồn cho s giao ti p c a h ự ế ủ ệ thống v i các thi t b vào ra ớ ế ị như: bàn phím, ổ đĩa, màn hình,… Chúng ta sẽ ần thay đổ c i mã nguồn cho bộ định thời timer trong dự án số 1
Thư mục “lib/”
Đây là thư mục tập hợp các thư viện chuẩn trong C ph c v cho các d án Gụ ụ ự ần như không cần thay đổi mã nguồn trong thư mục này Khi c n s d ng mầ ử ụ ột thư viện c ụ thể nào
ta ch c n s d ng kí hi u #include Mã nguỉ ầ ử ụ ệ ồn trong thư viện này được biên dịch dưới 2 dạng là “kernel” và “user”
Thư mục “lib/kernel/”
Đây là m t ph n cộ ầ ủa thư viện C mà được sử ụ d ng trong nhân c a hủ ệ điều hành Nó bao gồm cả ột số ể m ki u dữ liệ ự định nghĩa như: bitmaps, linked list hay hash table.u t
Thư mục “lib/user/”
Phần thư viện C được sử dụng trong các chương trình người dùng c a Pinủ tos,
Thư mục “tests/”
Trang 6Đây là thư mục chứa các kết quả chạy th c a các d án Ta có thử ủ ự ể thay đổi mã nguồn n u nó có ích trong quá trình ki m tra các dế ể ự án
Thư mục “examples/”
Đây là các ví dụ cho các chương trình người dùng được sử ụ d ng trong dự án số 2
Trang 7CHƯƠNG 2: DỰ ÁN LUỒNG – VẤN ĐỀ “PRIORITY SCHEDULING”
2.1 C u trúc dấ ữ liệ u và các hàm quan tr ọng
Bên c nh c u trúc danh sách (linked list) và c u trúc luạ ấ ấ ồng đã trình bày trong bài báo cáo trước thì đối với vấn đề này, chúng ta cần quan tâm đến một số cấu trúc khác như lock, semaphore, condition variable và các hàm liên quan
2.1.1 C u trúc semaphore ấ
Một biến semaphore được định nghĩa dưới d ng bi n c u trúc thông qua t khóa ạ ế ấ ừ
“struct” Cấu trúc này gồm 2 trường như sau
• unsigned value: Giá tr hi n tị ệ ại của semaphore
• struct list waiters: Danh sách các luồng đang đợi để chiếm semaphore
Một số hàm chức năng quen thuộc khi ta l p trình vậ ới semaphore:
• sema_init (): Hàm khởi tạo cho biến semaphore
• sema_down(): Đây là một phép toán th c hi n trên semaphore (P), nó s ự ệ ẽ tiến hành giảm giá trị c a semaphore xu ng ngay khi giá trủ ố ị này lớn hơn 0
• s ema_tr y_down(): Nó s ẽ thử ể ki m tra giá tr c a semaphore, n u lị ủ ế ớn hơn 0 thì sẽ
tiến hành gi m nó xuả ống 1 đơn vị và tr v giá trả ề ị TRUE, ngượ ạc l i thì sẽ ả v tr ề FALSE
• sema_up(): Cùng với P thì đây cũng là một phép toán th c hi n trên semaphore ự ệ (V), nó sẽ tăng giá trị ủ c a semaphore lên một đơn vị đồng thời đánh thức một trong các luồng đang đợi semaphore
2.1.2 C u trúc lock ấ
Một biến lock được định nghĩa dưới dạng biến cấu trúc thông qua từ khóa “struct”, gồm 2 trường như sau
• struct thread*holder: Trỏ đến luồng đang nắm giữ khóa
• struct semaphore semphore: Giá tr nh phân semaphore ph v quá trình kiị ị ụ ụ ểm soát quá trình truy nhập khóa
Trang 8Một số hàm quen thu c khi ta l p trình vộ ậ ới khóa:
• lock_init (struct lock*lock): hàm dùng để khởi tạo cho khóa
• lock_acquire (struct lock*lock): hàm này s d ng khi m t lu ng mu n chi m l y ử ụ ộ ồ ố ế ấ một khóa nào đó
• lock_try_acquire(struct lock*lock): hàm giúp m t lu ng cộ ồ ố chiếm l y khóa mà ấ
nó mong mu n, tr v giá tr TRUE n u chiố ả ề ị ế ếm khóa thành công và ngượ ạc l i tr ả
về giá tr FALSE n u chi m khóa thị ế ế ất bại
• lock_release (struct lock*lock): Khi m t lu ng hoàn thành công vi c và không ộ ồ ệ cần khóa n a thì nó sữ ẽ thực hiện giải phóng khóa đểcác luồng khác chiếm
2.1.3 C u trúc condition variable ấ
Một biến condition được định nghĩa dưới d ng m t c u trúc và bao g m mạ ộ ấ ồ ột trường duy nh t (struct list waiters) là danh sách các luấ ồng đang đợi Đối với loại cấu trúc này, ta cần có một vài lưu ý Một biến điều ki n (condition variable) sệ ẽ chỉ liên k t vế ới m t khóa, ộ nhưng một khóa thì sẽ liên kết với nhi u biề ến điều kiện, đây chính là quan hệ một nhiều
M t s hàm chúng ta c n quan tâm khi làm vi c v i bi n condition, có th kộ ố ầ ệ ớ ế ể ể đến như sau:
• cond_init (struct condition *cond): Hàm th c hi n quá trình kh i t o cho biự ệ ở ạ ến condition
• cond_wait (struct condition *cond, struct lock *lock): Các luồng đợi biến điều kiện và được đẩy vào hàng đợi
• cond_signal (struct condition *cond, struct lock *lock UNUSED): N u mế ột
luồng nào đó đang đợi biến điều kiện, hàm này sẽ ực hi n vith ệ ệc đánh thức một luồng trong danh sách đợi và luồng được đánh thức bắt buộc phải đang giữ khóa liên k t v i biế ớ ến điều kiện (khóa duy nhất)
• cond_broadcast (struct condition *cond, struct lock *lock): Đánh thức tất cả các luồng trong danh sách đợi Lưu ý rằng khóa liên kết bởi biến điều kiện bắt buộc phải được chiếm bởi luồng nào đó trước khi ta gọi hàm này
Trang 92.2 V ấn đề đặ t ra
Như chúng ta đã biết, mỗi hệ điều hành sẽ có một thành phần đảm nhiệm vai trò lập lịch cho các lu ng và ti n trình Hiồ ế ểu đơn giản, nó sẽ chọn lu ng ti p theo chi m gi ồ ế ế ữ CPU từ các luồng trong hàng đợi ready queue
Đối v i hớ ệ điêu hành Pintos, cơ chế ậ ị l p l ch mặc định c a nó là Round Robin, có ủ – nghĩa là cơ chế l p l ch tu n tậ ị ầ ự Cơ chế này hoạt động rất đơn giản, khi mỗi luồng kết thúc time slice của mình và nhường CPU cho lu ng khác, nó sồ ẽ trở ề cuối hàng đơi ready v queue, khi b l p l ch ch n lu ng tiộ ậ ị ọ ồ ếp theo được chi m CPU, nó s luôn luôn ch n ế ẽ ọ luồng
ở đầu hàng đợi Ta có thể ấ th y, với cơ chế này b lập l ch gộ ị ần như không quan tâm đến mức ưu tiên của các luồng mặc dù trong cấu trúc của luồng đã bao gồm thuộc tính priority nghĩa là độ ưu tiên
Hình 2 1 Cơ chế Round - Robin
Trong th c tự ế, cơ chế ậ ịch này thường ít khi đượ l p l c s d ng Do trong quá trình ử ụ hoạt động, một số luồng hoặc một số tiến trình sẽ có vai trò quan trọng, thường được ưu tiên hơn ví dụ các tiến trình tương tác với người dùng hay các tiến trình ảnh hưởng đến hoạt động của hệ thống Vì vậy, hệ điều hành thông thường sẽ phải quan tâm đến mức ưu tiên của các tiến trình để ậ ị l p l ch sao cho phù h p ợ
Bên c nh vạ ấn đề l p l ch, thì còn m t vậ ị ộ ấn đề khác liên quan đến vi c l a ch n lu ng ệ ự ọ ồ chiếm gi các bi n ph c v ữ ế ụ ụ cho quá trình đồng b khi các lu ng truy c p t i các vùng nh ộ ồ ậ ớ ớ critical section Giả s , chúng ta có m t danh sách các luử ộ ồng đang đợi m t bi n lock hoộ ế ặc
Trang 10một biến điều ki n Khi biệ ến lock đó được gi i phóng thì luả ồng có mức ưu tiên cao nhất cần được đánh thức đầu tiên
M c dù b l p lặ ộ ậ ịch ưu tiên đã cơ bản kh c phắ ục được nhược điểm c a b l p lủ ộ ậ ịch Round Robin, tuy v– ậy nó cũng có một số nhược điểm cố h u: ữ
• Hiện tượng “starvation”: Khi mà các luồng có mức ưu tiên cao luôn chiếm được CPU còn các luồng có ưu tiên thấp thì gần như không bao giờ chiếm được CPU
• Khi các luồng có ưu tiên cao thực hi n vi c ch ệ ệ ờ đợi ở các c ng IO quá lâu nó s ổ ẽ làm mất sự công bằng gi a các lu ng ữ ồ
Các nhược điểm này s ẽ được khắc ph c trong vụ ấn đề “Advanced Scheduler” của dự
án này
2.3 M c tiêu cụ ủa đề tài
Mục tiêu cơ bản cần hoàn thiện của đề tài là thay thế cơ chế lập lịch của hệ điều hành t Round Robin sang l p l ch theo mừ – ậ ị ức ưu tiên “Priority Scheduler” cùng với đó là giải quy t vế ấn đề liên quan đến vi c tranh ch p các bi n khóa và biệ ấ ế ến điều ki n gi a các ệ ữ luồng
2.4 Phương án giải quyết
Với mã ngu n nguyên b n c a Pintos, m i lu ng s có mồ ả ủ ỗ ồ ẽ ột trường thông tin chứa mức ưu tiên của nó (priority), và chúng ta sẽ có tổng cộng 64 mức ưu tiên trong khoảng từ
0 đến 63 Khi một luồng mới được tạo ra nếu ta không gán cho nó một mức ưu tiên cụ thể thì mức ưu tiên mặc định là 31 và trong quá trình các lu ng chiồ ếm CPU cũng như ra vào hàng đợi ready queue thì mức ưu tiên của nó
Dựa trên cơ sở này, vi c tìm ra gi i pháp cho vệ ả ấn đề đã nêu sẽ trở nên đơn giả ất n r nhiều
Trước hết đối với bộ lập lịch ưu tiên, chúng ta có thể có hai cách để triển khai bộ lập lịch ưu tiên
Trang 11• Cách 1: Chúng ta tổ chức hàng đợi ready queue m t cách có tr t t , các ộ ậ ự luồng được s p x p theo th t ắ ế ứ ự tăng dần (gi m d n) d a theo mả ầ ự ức độ ưu tiên của nó Khi l a ch n lu ng ti p theo chi m CPU, b lự ọ ồ ế ế ộ ập lịch sẽ chọn luồng nằm ở đầu hoặc ở cuối của hàng đợi tùy theo các s p x p ắ ế
• Cách 2: Không c n tầ ổ chức hàng đợi ready queue m t cách có tr t t Khi ộ ậ ự lập lịch bộ l p lậ ịch s tìm ra luẽ ồng có mức ưu tiên lớn nhất trong hàng đợi
và đẩy luồng đó vào chiếm CPU
Hình 2 2 Cơ chế Priority Scheduling
Với mỗi cách trên thì đều sẽ có ưu nhược điểm riêng, xét v b n ch t thì 2 cách nêu ề ả ấ trên thực ra không khác nhau, nó đều nh m mằ ục đích chọn ra lu ng có mồ ức ưu tiên cao nhất để thực hi n l p lệ ậ ịch Trong d án này em s ự ẽ chọn cách s ố 2 để tiến hành tri n khai b ể ộ lập lịch ưu tiên cho hệ điêu hành Pintos
Bên cạnh đó, khi một lu ng có mồ ức ưu tiên cao hơn luồng đang chiếm CPU được thêm vào hàng đợi ready queue thì luồng đang chiếm CPU c n phầ ải nhường CPU cho lu ng ồ
có mức ưu tiên cao hơn ngay lập tức
Trang 12Đố ới v i vấn đề chọn luồng được chiếm khóa hay biến điều kiện thì ý tưởng triển khai cũng hoàn toàn tương tự
2.4 Tri n khai c ể ụ thể
Trước hết, đối với bộ lập lịch ưu tiên, ta cần quan tâm đến hàm quyết định luồng nào s ẽ được chọn để chiếm CPU Khi đọc mã ngu n c a Pintos, ta có th d dàng phát hiồ ủ ể ễ ện
ra đó chính là hàm next_thread_to_run() Như vậy ta sẽ tiến hành thay đổi hàm đó để lựa chọn ra luồng có mức ưu tiên cao nhất trong hàng đợi ready queue
Để m b o khi m t lu ng có mđả ả ộ ồ ức độ ưu tiên cao hơn luồng đang chiếm CPU được thêm vào hàng đợi ready queue thì luồng đang chiếm CPU phải nhường CPU ngay l p tậ ức,
ta sẽ tiến hành thay đổi hàm thread_create()
Còn đối v i viớ ệc đảm b o lu ng có mả ồ ức ưu tiên cao nhất s là luẽ ồng được đánh thức trước để chiếm lấy khóa hoặc biến điều kiện Chúng ta sẽ tiến hành thay đổi 4 hàm trong file synch.c đó là các hàm sema_up (), sema_down(), cond_wait() và cond_signal() Để phục vụ cho quá trình thay đổi 4 hàm này em có vi t thêm 2 hàm khác là ế
compare_sema_priority() và compare_priority()
Cụ thể ự thay đổi củ s a mã nguồn được trình bày trong bảng sau:
Bảng 2 1 B ng t ng kả ổ ết các hàm được thêm mới và các hàm đư c sửa đổợ i trong vấn đề
“Priority Scheduling”
Hàm
bị
thay
đổi
next_thread_to_run(
) thread_set_priority()
sema_down() cond_wait() cond_signal()
Hàm
được
thêm
mới
compare_thread_p
riority()
compare_thread_pri ority()
compare_sema_pr iority()
compare_sem a_priority()
Trang 13CHƯƠNG 3: DỰ ÁN LUỒNG – VẤN ĐỀ “PRIORITY DONATION”
3.1 Các c u trúc d u quan trấ ữ liệ ọng
Các c u trúc c n s d ng trong vấ ầ ử ụ ấn đề này đều đã được nêu ở chương 2 như cấu trúc lock, condition và semaphore
3.2 V ấn đề đặ t ra
Sau khi tri n khai b l p l ch, chúng ta sể ộ ậ ị ẽ thấy m t vộ ấn đề ấ ập là đôi khi luồ b t c ng
có mức ưu tiên cao lại không được chiếm CPU mà thay vào đó là luồng có mức ưu tiên thấp hơn Hiện tượng này được gọi là “Priority Inversion” Hiện tượng này sẽ xảy ra khi
mà một lu ng có mồ ức ưu tiên cao đang đợi m t biộ ến khóa hoặc biến điều kiện nhưng biến này lại đang do một lu ng có mồ ức ưu tiên nắm gi ữ và chưa được giải phóng Để cụ thể hơn cho điều này ta đi xét ví dụ sau
Xét 3 lu ng lồ ần lượt như sau: luồng H có mức ưu tiên là 35, lu ng M có mồ ức ưu tiên là 33 và cu i cùng là lu ng L có mố ồ ức ưu tiên là 31 Luồng H đang chờ ộ m t khóa do luồng L chi m và hiế ện tượng có th ể được mô tả ằ b ng hình v ẽ sau
Hình 3 1 Vấn đề “Priority Inversion”
Ta có th d dàng phát hi n ra vể ễ ệ ấn đề ở đây, mặc dù lu ng M có mồ ức ưu tiên thấp hơn luồng H, nhưng nó lại chiếm được CPU do lu ng H phồ ải đợi khóa t ừ luồng L Rõ ràng tình huống này đã đi trái với thiết k ế ban đầu của chúng ta