LỜI NÓI ĐẦU
Hiện nay, khoa học kĩ thuật trên thế giới ngày càng phát triển mạnh mẽ. Khoa
học thuật đóng vai trò không thể thiếu trong đời sống hiện đại ngày nay của
chúng ta nó hiện diện trong từng sản phẩm, từng vật dụng chúng ta sử dụng
hàng ngày. Vì vậy việc học tập và đạo tạo, kế thừa và phát triển những thành tựu
khoa học cho thế hệ mới ngày nay cùng quan trọng đặc biệt thế hệ sinh
viên. Việc tiếp cận đó cần phải tiếp cận cả về mặt lí thuyết lẫn thực hành, như vậy
việc học tập và đào tạo mới thể đạt được hiệu quả tốt nhất, đáp ứng được cho
xã hội nguồn nhân lực khoa học kĩ thuật chất lượng cao. Trong qtrình học tập
học phần Hệ điều hành do thầy Phạm Văn Tiến giảng dạy chúng em đã được
hướng dẫn, trợ giáo để hoàn thành việc thực hành các dự án trong khóa học về hệ
điều hành Pintos.
Sau khi trải qua một khoảng thời gian, nhóm chúng em đã bản hoàn thành
việc lập trình đhiểu hơn về hệ điều hành Pintos, giải quyết được một vấn đề trong
hệ điều nh này. Trong bài báo o này, nhóm chúng em sẽ đi trình bày cụ thể
những gì đã làm được trong những tuần vừa qua thông qua 4 chương sau:
Chương 1: Giới thiệu hệ điều hành Pintos
Chương 2: Advanced Scheduler
Chương 3: Process Termination Messages
Chương 4: Kết luận
Nhóm xin chân thành cảm ơn TS đã tận tâm hướng dẫn chúng em trong quá
trình tìm hiểu và hoàn thiện báo cáo này!
MỤC LỤC
BẢNG PHÂN CÔNG CÔNG VIỆC .......................................................................................... 3
CHƯƠNG 1. GIỚI THIỆU HỆ ĐIỀU HÀNH PINTOS .......................................................... 3
1.1 Tổng quan về Pintos ........................................................................................................... 4
1.2 Cây thư mục nguồn ............................................................................................................ 4
1.3 Tổng quan về Threads........................................................................................................ 5
CHƯƠNG 2. Advanced Scheduler ............................................................................................. 8
2.1 Vấn đề Advanced Scheduler .............................................................................................. 8
2.2 Mô tả mục tiêu .................................................................................................................... 8
2.3 Phương pháp giải quyết ..................................................................................................... 9
2.4 Triển khai mã nguồn .......................................................................................................... 9
2.5 Mô tả mã nguồn đã sửa đổi, bổ sung .............................................................................. 10
2.6 Kết quả .............................................................................................................................. 11
CHƯƠNG 3. Process Termination Messages .......................................................................... 12
3.1 Đặt vấn đề ......................................................................................................................... 12
3.2 Mô tả mục tiêu .................................................................................................................. 13
3.3 Yêu cầu triển khai ............................................................................................................ 14
3.4 Triển khai mã nguồn ........................................................................................................ 14
3.5 Sửa đổi mã nguồn và bổ sung ......................................................................................... 15
3.6 Kết quả .............................................................................................................................. 16
CHƯƠNG 4. KẾT LUẬN ......................................................................................................... 17
TÀI LIỆU THAM KHẢO ......................................................................................................... 17
BẢNG PHÂN CÔNG CÔNG VIỆC
Các vấn đề
Cao Xuân Nghĩa
Vũ Đình Khải
Trần Bảo Duy
1. Advanced
Scheduler
- Xác định công thức priority,
tìm hiểu và viết code liên quan
, tổng hợp code và chạy :
thread_update_priority()
compare_threads_by_priority(
)
thread_update_priority_mlfqs(
)
- Xác định công thức
recent_cpu,tìm hiểu và viết
code liên quan : thread_tick
()
thread_update_recent_cpu()
thread_get_recent_cpu()
- Xác định công thức
load_avg,tìm hiểu và viết
code liên quan
thread_tick_one_second()
thread_get_nice()
thread_set_nice()
thread_get_load_avg()
2. Process
Termination
Messages
Tìm hiểu và viết code liên
quan setup_stack(),
process_is_parent_of (),
remove_child()
process_close_all()
process_init()
Tìm hiểu và viết code liên
quan:
process_execute ()
start_process()
extract_command_name()
extract_command_args()
Tìm hiểu và viết code liên
quan :
process_wait ()
process_exit()
load()
install_page()
CHƯƠNG 1.
GIỚI THIỆU HỆ ĐIỀU HÀNH PINTOS
Chương y giới thiệu tổng quan về hệ điều hành Pintos tổng quan về cây thư mục
nguồn của hệ điều hành Pintos
1.1 Tổng quan về Pintos
Pintos là một khung hệ điều hành đơn giản cho kiến trúc 80x86. Nó hỗ trợ kernel threads,
loading running user programs một file system, nhưng thực hiện tất cả những điều
này một cách rất đơn giản. Các cơ chế này còn có nhiều vấn đề cần khắc phục đhệ điều nh
có thể chạy một cách tối ưu.
Hình 1: 4 Project dựa trên hệ điều hành Pintos mà Stanford đưa ra
Ngoài ra Stanford đưa ra CS140 Problem Set 0: Synchronization Đồng bộ hóa để sinh
viên làm quen với mã nguồn của Pintos. Khi người dùng triển khai thành công (PASS các bài
TEST) c nội dung được đề ra này, hệ điều hành Pintos sẽ hoạt động hiệu quả, hiệu suất cao,
tiết kiêm các tài nguyên của bộ nhớ, năng lượng và thời gian của máy tính. Trong báo cáo s
sử dụng QEMU là trình mô phỏng.
1.2 Cây thư mục nguồn
Quan sát vào bên trong nguồn. Đây cấu trúc t mục trong “…/pintos-
anonmaster/src”
Thư mục
Mô tả
“threads/”
Mã nguồn cơ sở kernel, mà bạn sẽ thay đổi từ Project 1
“userprog/”
nguồn cho trình tải chương trình người dùng, bạn sẽ
sửa đổi từ Project 2
“vm/”
Một thư mục gần như trống rỗng. Bạn sẽ triển khai bộ nhớ ảo
ở đây trong Project 3
“filesys/”
nguồn cho hệ thống tệp bản. Bạn sẽ sdụng tệp này
bắt đầu với Project 2, nhưng bạn sẽ không sửa đổi cho đến
Project 4.
“devices/”
nguồn cho giao tiếp thiết bị I/O: bàn phím, bộ đếm thời
gian, đĩa, Bạn sẽ sửa đổi việc triển khai bộ hẹn giờ trong
Project 1
“lib/”
Đây là tập các thư viện C chuẩn, được biên dịch vào kernel và
các chương trình người dùng chạy dưới nó, bắt đầu từ Project 2.
Tiêu đề trong thư mục này được đưa vào bằng #include <…>
“lib/kernel/”
Các phần của thư viện C chỉ có trong kernel Pintos. Bao gồm
một số kiểu dữ liệu: bitmap, linked list, hash table.
“lib/user/”
Các phần của thư viện C chỉ trong chương trình người dùng.
“tests/”
Các bài test cho từng dự án. Bạn thể sửa đổi này nếu
nó giúp bạn kiểm tra nội dung của mình, nhưng chúng tôi sẽ thay
thế nó bằng mã gốc trước khi test thử nghiệm.
“examples/”
dụ cho chương trình người dùng được sử dụng trong Project
2
“misc/”
“utils/”
Những files này thể hữu ích nếu bạn quyết định thử làm việc
với Pintos trên máy tính riêng. Nếu không có thể bỏ qua chúng.
1.3 Tổng quan về Threads
Các trạng thái của tiến trình được mô tả ở hình dưới.
Hình 2: Sơ đồ FSM của một threads
Trong Pintos, các trạng thái của luồng được khai báo bởi cấu trúc “enum thread_status
THREAD_RUNNING: Luồng đang chiếm CPU và làm việc trong CPU.
THREAD_READY: Luồng sẵn sàng làm việc nhưng chưa được đưa vào CPU, được
đặt trong hàng đợi ready queue chờ đến lượt.
THREAD_BLOCKED: Luồng đang chờ một sự kiện nào đó xảy ra mới tiếp tục làm
việc. Khi đó luồng được đưa vào trạng thái THREAD_BLOCKED để nhường CPU
cho các luồng khác trong ready queue làm việc.
THREAD_DYING: Luồng đã thực hiện xong việc được TERMINATED. sẽ được
tiêu hủy.
Các hàm chuyển đổi giữa các trạng thái của luồng được tả ở hình dưới. Chúng được
khởi tạo trong “src/threads/thread.c”
Hình 3: Sơ đồ hàm chuyển trạng thái của threads
Cấu trúc của luồng được khai báo trong “threads/thread.h”:
tid_t_tid: Thread identifier
enum thread_status status: Thread state
char name[16]: Name (for debugging purpose)
uint8_t *stack: Saved stack pointer
int priority: Priority (from 0 to 63)
int base_priority: Base priority for priority donation
struct list_elem allelem: List element for all threads list
struct list_elem elem: List element
unit32_t *pagedir: Page directory
usigned magic: Detects stack overflow
CHƯƠNG 2. Advanced Scheduler
Chương này tả mục tiêu, phương pháp, triển khai nguồn, mô tả mã nguồn đã sửa
đổi, bổ sung giải quyết vấn đề Advanced Scheduler trong Project 1 của Pintos
2.1 Vấn đề Advanced Scheduler
Triển khai bộ lập lịch nâng cao để giảm thời gian phản hồi trung bình cho các tác vụ đang
chạy trên hệ thống .
Giống như bộ lập lịch ưu tiên, bộ lập lịch ng cao chọn luồng để chạy dựa trên mức độ
ưu tiên. Tuy nhiên, bộ lập lịch trình nâng cao không ưu tiên đóng góp. Vì vậy, bạn nên để bộ
lập lịch trình ưu tiên hoạt động, ngoại trừ thể để quyên góp ưu tiên, trước khi bạn bắt
đầu làm việc với bộ lập lịch trình nâng cao.
Bộ lập lịch biểu nâng cao sử dụng các phương trình để tính toán một số giá trị để nó đưa
ra quyết định.
2.2 Mô tả mục tiêu
Mục tiêu của bộ lập lịch mục đích chung cân bằng các nhu cầu lập lịch khác nhau của
luồng. Các luồng thực hiện nhiều I/O yêu cầu thời gian phản hồi nhanh để giữ cho các thiết
bị đầu vào đầu ra luôn bận rộn nhưng lại cần ít thời gian cho CPU. Mặt khác, các luồng
liên kết điện toán cần nhận được nhiều thời gian của CPU để hoàn thành công việc nhưng
không có yêu cầu về thời gian phản hồi nhanh. Các luồng khác nằm ở đâu đó ở giữa, với các
khoảng thời gian I/O được đánh dấu bằng các khoảng thời gian tính toán và do đó có các yêu
cầu thay đổi theo thời gian. Một bộ lập lịch được thiết kế tốt thường có thể đáp ứng đồng thời
các luồng với tất cả các yêu cầu này.
Loại bộ lập lịch này duy trì một số hàng đợi của các luồng sẵn sàng chạy, trong đó mỗi
hàng đợi chứa các luồng mức độ ưu tiên khác nhau. Tại bất kỳ thời điểm nào, bộ lập lịch
chọn một luồng từ hàng đợi không trống có mức độ ưu tiên cao nhất. Nếu hàng đợi mức
độ ưu tiên cao nhất chứa nhiều luồng, thì chúng sẽ chạy theo thứ tự "vòng tròn".
Nhiều khía cạnh của bộ lập lịch yêu cầu cập nhật dữ liệu sau một số tích tắc hẹn giờ nhất
định. Trong mọi trường hợp, những cập nhật này sẽ xảy ra trước khi bất kỳ luồng nhân thông
thường nào có cơ hội chạy, do đó, không có khả năng một luồng nhân có thể nhìn thấy giá trị
mới tăng timer_ticks()nhưng giá trị dữ liệu cũ của bộ lập lịch
2.3 Phương pháp giải quyết
Tính mức độ ưu tiên của luồng được cập nhật trong timer_interrupt trong một khoảng thời
gian cố định, đây cập nhật hệ thống load_avg recent_cpu của tất cả các luồng mỗi
TIMER_FREQ, cập nhật mức độ ưu tiên của luồng cứ sau 4 timer_ticks thêm một o
recent_cpu của mỗi thread chạy timer_tick, Mặc dù những gì được đề cập ở đây là để duy trì
64 lập lịch hàng đợi ưu tiên, nhưng bản chất của vẫn lập lịch ưu tiên, chúng ta thể
giữ mã lập lịch ưu tiên được viết trước đó và xóa ưu tiên đóng góp
Mỗi luồng có giá trị nice trong khoảng từ -20 đến 20 trực tiếp dưới sự kiểm soát của nó.
Mỗi luồng cũng có một mức độ ưu tiên, từ 0 ( PRI_MIN) đến 63 ( PRI_MAX), được tính toán
lại bằng cách sử dụng công thức sau mỗi lần đánh dấu thứ tư:
priority = PRI_MAX - (recent_cpu / 4) - (nice * 2).
Recent_cpu đo lượng thời gian CPU mà một luồng đã nhận được " recently". Trên mỗi dấu
tích của bộ đếm thời gian, recent_cpu của luồng đang chạy được tăng thêm 1. Mỗi giây
một lần, recent_cpu của mọi luồng được cập nhật theo cách này:
recent_cpu = (2*load_avg)/(2*load_avg + 1) * recent_cpu + nice.
load_avg ước tính số luồng trung bình sẵn sàng chạy trong một phút qua. Nó được khởi
tạo bằng 0 khi khởi động và được tính toán lại một lần mỗi giây như sau:
load_avg = (59/60)* load_avg + (1/60)* ready_threads .
trong đó ready_threads là số luồng đang chạy hoặc sẵn sàng chạy tại thời điểm cập nhật
(không bao gồm luồng không hoạt động).
2.4 Triển khai mã nguồn
Các hàm cần triển khai cho quá trình sửa đổi mã nguồn nằm trong file thread.c, thread.h
trong thư mục “src/threads/” và timer.c
Sửa hàm thread_tick () để tính toán recent_cpu
Thêm hàm thread_update_priority_mlfqs() cập nhật priority
Thêm hàm thread_update_recent_cpu() và thread_tick_one_second()
Thêm hàm thread_set_nice()
Thêm hàm thread_get_nice()
Thêm hàm thread_get_load_avg() để tính toán load_avg
Thêm hàm thread_get_recent_cpu() để tính toán recent_cpu
Thêm giá trị biến toàn cục: fixed_t load_avg;
Khởi tạo : load_avg = 0;
2.5 Mô tả mã nguồn đã sửa đổi, bổ sung
Các biến được thêm vào cấu trúc thread trong threads/thread.h:
Thêm 2 biến int nice fixed_t recent_cpu Các m được thêm vào
threads/thread.c:
thread_update_recent_cpu() thread_tick_one_second(): đầu tiên tính
load_avg giá trị theo kích thước của hàng đợi sẵn sàng, sau đó cập nhật giá
trị giá trị load_avg của tất cả các quy trình theo giá trị của recent_cpu
priority
thread_ update_priority_mlfqs() : Cập nhật giá trị của tiến trình hiện tại
Lưu ý đầu tiên của priority mỗi luỗng phải nằm trong khoảng từ 0 -63
(PRI_MIN - PRI_MAX).
thread_set_nice() : Đặt giá trị nice của luồng hiện tại thành NICE.
thread_get_nice(): Trả về giá trị nice của luồng hiện tại
thread_get_load_avg(): Trả về 100 lần mức tải trung bình của hệ thống.
thread_get_recent_cpu(): Trả về 100 lần giá trị recent_cpu của luồng hiện
tại
Các biến và hàm thêm vào threads/thread.c:
Khi thread được khởi tạo, gán giá trị ban đầu cho 2 biến này để sửa đổi
init_thread():
Khởi tạo: nice = 0
recent_cpu = 0
2.6 Kết quả
Kết quả sau khi kiểm tra bằng lệnh make check đã pass 9/9 test case
Hình 4: Kết quả sau khi chạy lệnh make check
CHƯƠNG 3. Process Termination Messages
Chương này tả mục tiêu, phương pháp, triển khai nguồn, tả nguồn đã
sửa đổi, bổ sung giải quyết vấn đề Process Termination Messages trong Project 2 của Pintos.
3.1 Đặt vấn đề
Mỗi tiến trình chấm dứt khi kết thúc thực hiện câu lệnh cuối cùng yêu cầu hệ điều
hành xóa nó bằng cách sử dụng lệnh gọi exit() trong hệ thống. Tại thời điểm đó, tiến trình con
có thể trả về 1 giá trị trạng thái thường là một số nguyên cho tiến trình mẹ của thông qua
lệnh gọi wait() hệ thống .
Tất cả các tài nguyên của tiến trình bao gồm cả bộ nhớ ảo bộ nhớ vật lý, mở tệp , bộ
đêm vào ra I/O đều được hệ điều hành phân bổ.
Chúng ta vừa tìm hiểu về việc chấm dứt tiến trình , bây giờ chúng ta thấy rằng việc chấm
dứt 1 tiến trình xảy ra khi câu lệnh cuối cùng của tiến trình đã được thực và tại thời điểm đó
đã chấm dứt tiến trình đã xảy ra nhưng ngắt cũng có thể xảy ra trong các trường hợp khác.
Một tiến trình thể gây ra việc chấm dứt tiến trình khác thông qua một cuộc gọi hệ thống
thích hợp . Thông thường , một cuộc gọi như vậy chỉ thể được gọi bởi tiến trình mẹ của
tiến trình đó thì tiến trình con sẽ bị hệ điều hành chấm dứt. Nếu không thì ,người dùng có thể
tự ý hủy công việc của nhau. Và bây giờ tiến trình mẹ thể chấm dứt tiến trình con với nhiều
lý do như:
Tiến trình con đã vượt quá việc sử dụng một số tài nguyên nó được phân bổ (để
xác định xem điều này đã xảy ra, tiến trình mphải có chế kiểm tra tình trạng
của tiến trình con)
Nhiệm vụ được giao cho tiến trình con không còn cần thiết nữa
Tiến trình mẹ đang thoát và hệ điều hành không cho phép một tiến trình con có thể
tiếp tục nếu tiến trình mẹ đã kết thúc.
Một tiến trình mẹ bằng cách sử dụng lệnh gọi hệ thống wait(). Cuộc gọi hệ thống
wait() được truyền một tham số cho phép tiến trình mẹ có được trạng thái thoát của
tiến trình con. Cuộc gọi hệ thống này cũng trả về định danh quy trình của tiến trình
con đã kết thúc để tiến trình mẹ có thể biết tiến trình con nào của nó đã kết thúc.
Hình 5: Tạo tiến trình bằng cách sử dụng fork() system call
Trong project 2 việc khởi chạy chương trình người dùng đồng nghĩa rằng chương trình
đó sẽ không được toàn quyền kiểm soát hoàn toàn hệ thống. Các chương trình sẽ chạy trên
không gian người dùng bị giới hạn tài nguyên bởi hệ điều hành. Để thể chạy được
chương trình cần được nạp vào file system, các chương trình này sẽ cần truyền tham số xuống,
hoặc tác động lên hệ thống thông qua yêu cầu system call. Hiện tại Pintos đã xây dựng sẵn
file system nhưng chưa có cơ chế truyền tham số chưa system call, vì vậy việc chạy c
chương trình trong thư mục src/examples sẽ trả về lỗi page fault.
3.2 Mô tả mục tiêu
Bất cứ khi nào một quy trình người dùng kết thúc, được gọi exit hoặc bất kỳ
lý do nào khác, hãy in tên và mã thoát của quy trình, được định dạng như thể được in bởi
. Tên được in phải là tên đầy đủ được truyền cho , bỏ qua các đối s dòng lệnh. Không in
các thông báo này khi một luồng hạt nhân không phải quá trình người dùng kết thúc
hoặc khi cuộc gọi hệ thống được gọi. Thông báo tùy chọn khi một quá trình không tải
được. printf ("%s: exit(%d)\n", ...);process_execute()halt
Ngoài điều này, không in bất kỳ tin nhắn nào khác Pintos được cung cấp chưa in.
Bạn có thể tìm thấy các thông báo bổ sung hữu ích trong quá trình gỡ lỗi, nhưng chúng s
gây nhầm lẫn cho các tập lệnh chấm điểm và do đó làm giảm điểm của bạn.
3.3 Yêu cầu triển khai
- Trường hợp chương trình fail to load
Tại file process.c tmục src/userprog một hàm void start_process (void *file_name)
được xây dựng sẵn để load tiến trình người dùng khởi chạy nó. Trong hàm này, một biến
success theo dõi trạng thái load của tiến trình, nếu tiến trình fail to load hàm sgọi m
thread_exit ().
- Trường hợp chương trình bị terminate do phát sinh lỗi page fault
Tại file exeption.c thư mục src/userprog hàm void page fault (struct intr_frame *f) được
xây dựng để xử lỗi page fault hàm sẽ xác định nguyên nhân gây ra lỗi (lỗi not_present hoặc
lỗi write hoặc lỗi user) sau đó gọi hàm kill (f). Hàm static void kill (struct intr_frame *f) được
xây dưng sẵn để chấm dứt tiến trình lỗi. Hàm kill sẽ đọc cờ ngắt f->cs để xác lỗi bắt nguồn
từ user's code hay kernel’ code, từ đó thể thêm một hàm printf để in ra thông báo trong
trường hợp lỗi bắt nguồn từ user's code.
- Trường hợp tiến trình bị kết thúc do bị gọi exit
Khi thực hiện truyền đối số thành công, các chương trình người dùng sẽ được thực hiện
đúng cách và kết thúc bằng cách gọi exit() trong phần process_exit().
Để lấy được tên chương trình cần tạo một hàm phân tích cú pháp chuỗi đối số truyền vào
extract_command_name(fn_copy, cmd_name); sau đó chỉnh sửa hàm load() được gọi trong
start_process() với tên tệp đã được phân tích pháp khi chạy chương trình. Do chưa thực
hiện process_wait() nên tiến trình mẹ có thể sẽ kết thúc trước mà không đợi tiến trình con
3.4 Triển khai mã nguồn
Các hàm và các biến được triển khai trong file:
userprog/process.c và process.h
3.5 Sửa đổi mã nguồn và bổ sung
Các biến và hàm được thêm vào userprog/process.h:
o void process_exit (int status); o void
process_init(void);
Chỉnh sửa khung hàm được cấp sẵn: userprog/process.c:
Thêm hàm static bool setup_stack() :cài đặt con trỏ ngăn xếp .
Sửa đổi chức năng process_execute ()start_process()
Sửa đổi chức năng process_wait () process_exit(): Trong hàm process_wait vòng lặp
và process_exit để in ra khi tiến trình kết thúc.
Thêm 2 hàm bool process_is_parent_of () và void remove_child(): kiểm tra phải tiến
trình mẹ hay không và xóa tiến trình con .
Chỉnh sửa hàm load() , install_page()
Thêm 2 hàm extract_command_name()extract_command_args()
Thêm 2 hàm process_close_all()process_init()
3.6 Kết quả
Sau khi kiểm tra bằng lệnh make check thì đã pass:
Hình 6: Kết quả sau khi đã make check test termination message process
CHƯƠNG 4. KẾT LUẬN
Sau khi m hiểu đưa ra giải pháp, vấn đề “Advanced Scheduler” trong Project 1 của
Pintos đã được giải quyết. Trong Project 2, nhóm em đã thực hiện Process Termination
Message . Về cơ bản đã được nhóm em kiểm tra và chạy thử nghiệm thành công. Sau khi kết
thúc môn học, và có nhiều thời gian hơn, chúng em sẽ có gắng dùng những kiến thức đã tính
luỹ từ môn học để hoàn thành các project còn lại trong dự án Pintos .
Chúng em xin chân thành cảm ơn thầy đã hướng dẫn chúng em để hoàn thành dự án này.
TÀI LIỆU THAM KHẢO
https://web.stanford.edu/~ouster/cgi-bin/cs140-spring20/pintos/pintos_2.html#SEC15
https://www.scs.stanford.edu/21wi-cs140/pintos/pintos_2.html
Hyperlink project: https://github.com/nghia3040khai2927duy2805/pintos_project.git

Preview text:

LỜI NÓI ĐẦU
Hiện nay, khoa học kĩ thuật trên thế giới ngày càng phát triển mạnh mẽ. Khoa
học kĩ thuật đóng vai trò không thể thiếu trong đời sống hiện đại ngày nay của
chúng ta nó hiện diện trong từng sản phẩm, từng vật dụng mà chúng ta sử dụng
hàng ngày. Vì vậy việc học tập và đạo tạo, kế thừa và phát triển những thành tựu
khoa học cho thế hệ mới ngày nay là vô cùng quan trọng đặc biệt là thế hệ sinh
viên. Việc tiếp cận đó cần phải tiếp cận cả về mặt lí thuyết lẫn thực hành, như vậy
việc học tập và đào tạo mới có thể đạt được hiệu quả tốt nhất, đáp ứng được cho
xã hội nguồn nhân lực khoa học kĩ thuật chất lượng cao. Trong quá trình học tập
học phần Hệ điều hành do thầy Phạm Văn Tiến giảng dạy chúng em đã được
hướng dẫn, trợ giáo để hoàn thành việc thực hành các dự án trong khóa học về hệ điều hành Pintos.
Sau khi trải qua một khoảng thời gian, nhóm chúng em đã cơ bản hoàn thành
việc lập trình để hiểu hơn về hệ điều hành Pintos, giải quyết được một vấn đề trong
hệ điều hành này. Trong bài báo cáo này, nhóm chúng em sẽ đi trình bày cụ thể
những gì đã làm được trong những tuần vừa qua thông qua 4 chương sau:
Chương 1: Giới thiệu hệ điều hành Pintos
Chương 2: Advanced Scheduler
Chương 3: Process Termination Messages
Chương 4: Kết luận
Nhóm xin chân thành cảm ơn TS đã tận tâm hướng dẫn chúng em trong quá
trình tìm hiểu và hoàn thiện báo cáo này! MỤC LỤC
BẢNG PHÂN CÔNG CÔNG VIỆC .......................................................................................... 3
CHƯƠNG 1. GIỚI THIỆU HỆ ĐIỀU HÀNH PINTOS .......................................................... 3
1.1 Tổng quan về Pintos ........................................................................................................... 4
1.2 Cây thư mục nguồn ............................................................................................................ 4
1.3 Tổng quan về Threads........................................................................................................ 5
CHƯƠNG 2. Advanced Scheduler ............................................................................................. 8
2.1 Vấn đề Advanced Scheduler .............................................................................................. 8
2.2 Mô tả mục tiêu .................................................................................................................... 8
2.3 Phương pháp giải quyết ..................................................................................................... 9
2.4 Triển khai mã nguồn .......................................................................................................... 9
2.5 Mô tả mã nguồn đã sửa đổi, bổ sung .............................................................................. 10
2.6 Kết quả .............................................................................................................................. 11
CHƯƠNG 3. Process Termination Messages .......................................................................... 12
3.1 Đặt vấn đề ......................................................................................................................... 12
3.2 Mô tả mục tiêu .................................................................................................................. 13
3.3 Yêu cầu triển khai ............................................................................................................ 14
3.4 Triển khai mã nguồn ........................................................................................................ 14
3.5 Sửa đổi mã nguồn và bổ sung ......................................................................................... 15
3.6 Kết quả .............................................................................................................................. 16
CHƯƠNG 4. KẾT LUẬN ......................................................................................................... 17
TÀI LIỆU THAM KHẢO ......................................................................................................... 17
BẢNG PHÂN CÔNG CÔNG VIỆC
Các vấn đề Cao Xuân Nghĩa Vũ Đình Khải Trần Bảo Duy
1. Advanced - Xác định công thức priority,
- Xác định công thức - Xác định công thức Scheduler
tìm hiểu và viết code liên quan recent_cpu,tìm hiểu và viết load_avg,tìm hiểu và viết
, tổng hợp code và chạy :
code liên quan : thread_tick code liên quan
thread_update_priority() ()
thread_tick_one_second()
compare_threads_by_priority( thread_update_recent_cpu() thread_get_nice() )
thread_get_recent_cpu() thread_set_nice()
thread_update_priority_mlfqs( thread_get_load_avg() ) 2. Process
Tìm hiểu và viết code liên
Tìm hiểu và viết code liên
Tìm hiểu và viết code liên
Termination quan setup_stack(), quan: quan : Messages
process_is_parent_of (), process_execute () process_wait () remove_child() start_process() process_exit() process_close_all() extract_command_name() load() process_init() extract_command_args() install_page()
CHƯƠNG 1. GIỚI THIỆU HỆ ĐIỀU HÀNH PINTOS
Chương này giới thiệu tổng quan về hệ điều hành Pintos và tổng quan về cây thư mục
nguồn của hệ điều hành Pintos
1.1 Tổng quan về Pintos
Pintos là một khung hệ điều hành đơn giản cho kiến trúc 80x86. Nó hỗ trợ kernel threads,
loading và running user programs và một file system, nhưng nó thực hiện tất cả những điều
này một cách rất đơn giản. Các cơ chế này còn có nhiều vấn đề cần khắc phục để hệ điều hành
có thể chạy một cách tối ưu.
Hình 1: 4 Project dựa trên hệ điều hành Pintos mà Stanford đưa ra
Ngoài ra Stanford đưa ra CS140 Problem Set 0: Synchronization – Đồng bộ hóa để sinh
viên làm quen với mã nguồn của Pintos. Khi người dùng triển khai thành công (PASS các bài
TEST) các nội dung được đề ra này, hệ điều hành Pintos sẽ hoạt động hiệu quả, hiệu suất cao,
tiết kiêm các tài nguyên của bộ nhớ, năng lượng và thời gian của máy tính. Trong báo cáo sẽ
sử dụng QEMU là trình mô phỏng.
1.2 Cây thư mục nguồn
Quan sát vào bên trong mã nguồn. Đây là cấu trúc thư mục trong “…/pintos- anonmaster/src” Thư mục Mô tả “threads/”
Mã nguồn cơ sở kernel, mà bạn sẽ thay đổi từ Project 1 “userprog/”
Mã nguồn cho trình tải chương trình người dùng, mà bạn sẽ sửa đổi từ Project 2 “vm/”
Một thư mục gần như trống rỗng. Bạn sẽ triển khai bộ nhớ ảo ở đây trong Project 3 “filesys/”
Mã nguồn cho hệ thống tệp cơ bản. Bạn sẽ sử dụng tệp này
bắt đầu với Project 2, nhưng bạn sẽ không sửa đổi nó cho đến Project 4. “devices/”
Mã nguồn cho giao tiếp thiết bị I/O: bàn phím, bộ đếm thời
gian, đĩa, … Bạn sẽ sửa đổi việc triển khai bộ hẹn giờ trong Project 1 “lib/”
Đây là tập các thư viện C chuẩn, được biên dịch vào kernel và
các chương trình người dùng chạy dưới nó, bắt đầu từ Project 2.
Tiêu đề trong thư mục này được đưa vào bằng #include <…> “lib/kernel/”
Các phần của thư viện C chỉ có trong kernel Pintos. Bao gồm
một số kiểu dữ liệu: bitmap, linked list, hash table. “lib/user/”
Các phần của thư viện C chỉ có trong chương trình người dùng. “tests/”
Các bài test cho từng dự án. Bạn có thể sửa đổi mã này nếu
nó giúp bạn kiểm tra nội dung của mình, nhưng chúng tôi sẽ thay
thế nó bằng mã gốc trước khi test thử nghiệm. “examples/”
Ví dụ cho chương trình người dùng được sử dụng trong Project 2 “misc/”
Những files này có thể hữu ích nếu bạn quyết định thử làm việc “utils/”
với Pintos trên máy tính riêng. Nếu không có thể bỏ qua chúng.
1.3 Tổng quan về Threads
Các trạng thái của tiến trình được mô tả ở hình dưới.
Hình 2: Sơ đồ FSM của một threads
Trong Pintos, các trạng thái của luồng được khai báo bởi cấu trúc “enum thread_status
THREAD_RUNNING: Luồng đang chiếm CPU và làm việc trong CPU.
THREAD_READY: Luồng sẵn sàng làm việc nhưng chưa được đưa vào CPU, được
đặt trong hàng đợi ready queue chờ đến lượt.
THREAD_BLOCKED: Luồng đang chờ một sự kiện nào đó xảy ra mới tiếp tục làm
việc. Khi đó luồng được đưa vào trạng thái THREAD_BLOCKED để nhường CPU
cho các luồng khác trong ready queue làm việc.
THREAD_DYING: Luồng đã thực hiện xong việc và được TERMINATED. Nó sẽ được tiêu hủy.
Các hàm chuyển đổi giữa các trạng thái của luồng được mô tả ở hình dưới. Chúng được
khởi tạo trong “src/threads/thread.c”
Hình 3: Sơ đồ hàm chuyển trạng thái của threads
Cấu trúc của luồng được khai báo trong “threads/thread.h”:
tid_t_tid: Thread identifier
enum thread_status status: Thread state
char name[16]: Name (for debugging purpose)
uint8_t *stack: Saved stack pointer
int priority: Priority (from 0 to 63)
int base_priority: Base priority for priority donation
struct list_elem allelem: List element for all threads list
struct list_elem elem: List element
unit32_t *pagedir: Page directory
usigned magic: Detects stack overflow
CHƯƠNG 2. Advanced Scheduler
Chương này mô tả mục tiêu, phương pháp, triển khai mã nguồn, mô tả mã nguồn đã sửa
đổi, bổ sung giải quyết vấn đề Advanced Scheduler trong Project 1 của Pintos
2.1 Vấn đề Advanced Scheduler
Triển khai bộ lập lịch nâng cao để giảm thời gian phản hồi trung bình cho các tác vụ đang chạy trên hệ thống .
Giống như bộ lập lịch ưu tiên, bộ lập lịch nâng cao chọn luồng để chạy dựa trên mức độ
ưu tiên. Tuy nhiên, bộ lập lịch trình nâng cao không ưu tiên đóng góp. Vì vậy, bạn nên để bộ
lập lịch trình ưu tiên hoạt động, ngoại trừ có thể là để quyên góp ưu tiên, trước khi bạn bắt
đầu làm việc với bộ lập lịch trình nâng cao.
Bộ lập lịch biểu nâng cao sử dụng các phương trình để tính toán một số giá trị để nó đưa ra quyết định.
2.2 Mô tả mục tiêu
Mục tiêu của bộ lập lịch mục đích chung là cân bằng các nhu cầu lập lịch khác nhau của
luồng. Các luồng thực hiện nhiều I/O yêu cầu thời gian phản hồi nhanh để giữ cho các thiết
bị đầu vào và đầu ra luôn bận rộn nhưng lại cần ít thời gian cho CPU. Mặt khác, các luồng
liên kết điện toán cần nhận được nhiều thời gian của CPU để hoàn thành công việc nhưng
không có yêu cầu về thời gian phản hồi nhanh. Các luồng khác nằm ở đâu đó ở giữa, với các
khoảng thời gian I/O được đánh dấu bằng các khoảng thời gian tính toán và do đó có các yêu
cầu thay đổi theo thời gian. Một bộ lập lịch được thiết kế tốt thường có thể đáp ứng đồng thời
các luồng với tất cả các yêu cầu này.
Loại bộ lập lịch này duy trì một số hàng đợi của các luồng sẵn sàng chạy, trong đó mỗi
hàng đợi chứa các luồng có mức độ ưu tiên khác nhau. Tại bất kỳ thời điểm nào, bộ lập lịch
chọn một luồng từ hàng đợi không trống có mức độ ưu tiên cao nhất. Nếu hàng đợi có mức
độ ưu tiên cao nhất chứa nhiều luồng, thì chúng sẽ chạy theo thứ tự "vòng tròn".
Nhiều khía cạnh của bộ lập lịch yêu cầu cập nhật dữ liệu sau một số tích tắc hẹn giờ nhất
định. Trong mọi trường hợp, những cập nhật này sẽ xảy ra trước khi bất kỳ luồng nhân thông
thường nào có cơ hội chạy, do đó, không có khả năng một luồng nhân có thể nhìn thấy giá trị
mới tăng timer_ticks()nhưng giá trị dữ liệu cũ của bộ lập lịch
2.3 Phương pháp giải quyết
Tính mức độ ưu tiên của luồng được cập nhật trong timer_interrupt trong một khoảng thời
gian cố định, ở đây là cập nhật hệ thống load_avg và recent_cpu của tất cả các luồng mỗi
TIMER_FREQ, cập nhật mức độ ưu tiên của luồng cứ sau 4 timer_ticks và thêm một vào
recent_cpu của mỗi thread chạy timer_tick, Mặc dù những gì được đề cập ở đây là để duy trì
64 lập lịch hàng đợi ưu tiên, nhưng bản chất của nó vẫn là lập lịch ưu tiên, chúng ta có thể
giữ mã lập lịch ưu tiên được viết trước đó và xóa ưu tiên đóng góp
Mỗi luồng có giá trị nice trong khoảng từ -20 đến 20 trực tiếp dưới sự kiểm soát của nó.
Mỗi luồng cũng có một mức độ ưu tiên, từ 0 ( PRI_MIN) đến 63 ( PRI_MAX), được tính toán
lại bằng cách sử dụng công thức sau mỗi lần đánh dấu thứ tư:
priority = PRI_MAX - (recent_cpu / 4) - (nice * 2).
Recent_cpu đo lượng thời gian CPU mà một luồng đã nhận được " recently". Trên mỗi dấu
tích của bộ đếm thời gian, recent_cpu của luồng đang chạy được tăng thêm 1. Mỗi giây
một lần, recent_cpu của mọi luồng được cập nhật theo cách này:
recent_cpu = (2*load_avg)/(2*load_avg + 1) * recent_cpu + nice.
load_avg ước tính số luồng trung bình sẵn sàng chạy trong một phút qua. Nó được khởi
tạo bằng 0 khi khởi động và được tính toán lại một lần mỗi giây như sau:
load_avg = (59/60)* load_avg + (1/60)* ready_threads .
trong đó ready_threads là số luồng đang chạy hoặc sẵn sàng chạy tại thời điểm cập nhật
(không bao gồm luồng không hoạt động).
2.4 Triển khai mã nguồn
Các hàm cần triển khai cho quá trình sửa đổi mã nguồn nằm trong file thread.c, thread.h
trong thư mục “src/threads/” và timer.c
• Sửa hàm thread_tick () để tính toán recent_cpu
• Thêm hàm thread_update_priority_mlfqs() cập nhật priority
• Thêm hàm thread_update_recent_cpu() và thread_tick_one_second()
• Thêm hàm thread_set_nice()
• Thêm hàm thread_get_nice()
• Thêm hàm thread_get_load_avg() để tính toán load_avg
• Thêm hàm thread_get_recent_cpu() để tính toán recent_cpu
• Thêm giá trị biến toàn cục: fixed_t load_avg;
• Khởi tạo : load_avg = 0;
2.5 Mô tả mã nguồn đã sửa đổi, bổ sung
 Các biến được thêm vào cấu trúc thread trong threads/thread.h:
• Thêm 2 biến int nicefixed_t recent_cpu  Các hàm được thêm vào
threads/thread.c:
thread_update_recent_cpu() và thread_tick_one_second(): đầu tiên tính
load_avg giá trị theo kích thước của hàng đợi sẵn sàng, sau đó cập nhật giá
trị và giá trị load_avg của tất cả các quy trình theo giá trị của recent_cpu priority
thread_ update_priority_mlfqs() : Cập nhật giá trị của tiến trình hiện tại
Lưu ý đầu tiên của priority mỗi luỗng phải nằm trong khoảng từ 0 -63
(PRI_MIN - PRI_MAX).
thread_set_nice() : Đặt giá trị nice của luồng hiện tại thành NICE.
thread_get_nice(): Trả về giá trị nice của luồng hiện tại
thread_get_load_avg(): Trả về 100 lần mức tải trung bình của hệ thống.
thread_get_recent_cpu(): Trả về 100 lần giá trị recent_cpu của luồng hiện tại
 Các biến và hàm thêm vào threads/thread.c:
Khi thread được khởi tạo, gán giá trị ban đầu cho 2 biến này để sửa đổi init_thread(): Khởi tạo: nice = 0 recent_cpu = 0 2.6 Kết quả
Kết quả sau khi kiểm tra bằng lệnh make check đã pass 9/9 test case
Hình 4: Kết quả sau khi chạy lệnh make check
CHƯƠNG 3. Process Termination Messages
Chương này mô tả mục tiêu, phương pháp, triển khai mã nguồn, mô tả mã nguồn đã
sửa đổi, bổ sung giải quyết vấn đề Process Termination Messages trong Project 2 của Pintos. 3.1 Đặt vấn đề
Mỗi tiến trình chấm dứt khi nó kết thúc thực hiện câu lệnh cuối cùng và yêu cầu hệ điều
hành xóa nó bằng cách sử dụng lệnh gọi exit() trong hệ thống. Tại thời điểm đó, tiến trình con
có thể trả về 1 giá trị trạng thái thường là một số nguyên cho tiến trình mẹ của nó thông qua
lệnh gọi wait() hệ thống .
Tất cả các tài nguyên của tiến trình bao gồm cả bộ nhớ ảo và bộ nhớ vật lý, mở tệp , bộ
đêm vào ra I/O đều được hệ điều hành phân bổ.
Chúng ta vừa tìm hiểu về việc chấm dứt tiến trình , bây giờ chúng ta thấy rằng việc chấm
dứt 1 tiến trình xảy ra khi câu lệnh cuối cùng của tiến trình đã được thực và tại thời điểm đó
đã chấm dứt tiến trình đã xảy ra nhưng ngắt cũng có thể xảy ra trong các trường hợp khác.
Một tiến trình có thể gây ra việc chấm dứt tiến trình khác thông qua một cuộc gọi hệ thống
thích hợp . Thông thường , một cuộc gọi như vậy chỉ có thể được gọi bởi tiến trình mẹ của
tiến trình đó thì tiến trình con sẽ bị hệ điều hành chấm dứt. Nếu không thì ,người dùng có thể
tự ý hủy công việc của nhau. Và bây giờ tiến trình mẹ có thể chấm dứt tiến trình con với nhiều lý do như:
• Tiến trình con đã vượt quá việc sử dụng một số tài nguyên mà nó được phân bổ (để
xác định xem điều này đã xảy ra, tiến trình mẹ phải có cơ chế kiểm tra tình trạng của tiến trình con)
• Nhiệm vụ được giao cho tiến trình con không còn cần thiết nữa
• Tiến trình mẹ đang thoát và hệ điều hành không cho phép một tiến trình con có thể
tiếp tục nếu tiến trình mẹ đã kết thúc.
• Một tiến trình mẹ bằng cách sử dụng lệnh gọi hệ thống wait(). Cuộc gọi hệ thống
wait() được truyền một tham số cho phép tiến trình mẹ có được trạng thái thoát của
tiến trình con. Cuộc gọi hệ thống này cũng trả về định danh quy trình của tiến trình
con đã kết thúc để tiến trình mẹ có thể biết tiến trình con nào của nó đã kết thúc.
Hình 5: Tạo tiến trình bằng cách sử dụng fork() system call
Trong project 2 việc khởi chạy chương trình người dùng đồng nghĩa rằng chương trình
đó sẽ không được toàn quyền kiểm soát hoàn toàn hệ thống. Các chương trình sẽ chạy trên
không gian người dùng và bị giới hạn tài nguyên bởi hệ điều hành. Để có thể chạy được
chương trình cần được nạp vào file system, các chương trình này sẽ cần truyền tham số xuống,
hoặc tác động lên hệ thống thông qua yêu cầu system call. Hiện tại Pintos đã xây dựng sẵn
file system nhưng chưa có cơ chế truyền tham số và chưa có system call, vì vậy việc chạy các
chương trình trong thư mục src/examples sẽ trả về lỗi page fault.
3.2 Mô tả mục tiêu
Bất cứ khi nào một quy trình người dùng kết thúc, vì nó được gọi exit hoặc vì bất kỳ
lý do nào khác, hãy in tên và mã thoát của quy trình, được định dạng như thể được in bởi
. Tên được in phải là tên đầy đủ được truyền cho , bỏ qua các đối số dòng lệnh. Không in
các thông báo này khi một luồng hạt nhân không phải là quá trình người dùng kết thúc
hoặc khi cuộc gọi hệ thống được gọi. Thông báo là tùy chọn khi một quá trình không tải
được. printf ("%s: exit(%d)\n", ...);process_execute()halt
Ngoài điều này, không in bất kỳ tin nhắn nào khác mà Pintos được cung cấp chưa in.
Bạn có thể tìm thấy các thông báo bổ sung hữu ích trong quá trình gỡ lỗi, nhưng chúng sẽ
gây nhầm lẫn cho các tập lệnh chấm điểm và do đó làm giảm điểm của bạn.
3.3 Yêu cầu triển khai -
Trường hợp chương trình fail to load
Tại file process.c thư mục src/userprog một hàm void start_process (void *file_name)
được xây dựng sẵn để load tiến trình người dùng và khởi chạy nó. Trong hàm này, một biến
success theo dõi trạng thái load của tiến trình, nếu tiến trình fail to load hàm sẽ gọi hàm thread_exit (). -
Trường hợp chương trình bị terminate do phát sinh lỗi page fault
Tại file exeption.c thư mục src/userprog hàm void page fault (struct intr_frame *f) được
xây dựng để xử lý lỗi page fault hàm sẽ xác định nguyên nhân gây ra lỗi (lỗi not_present hoặc
lỗi write hoặc lỗi user) sau đó gọi hàm kill (f). Hàm static void kill (struct intr_frame *f) được
xây dưng sẵn để chấm dứt tiến trình lỗi. Hàm kill sẽ đọc cờ ngắt f->cs để xác lỗi bắt nguồn
từ user's code hay kernel’ code, từ đó có thể thêm một hàm printf để in ra thông báo trong
trường hợp lỗi bắt nguồn từ user's code. -
Trường hợp tiến trình bị kết thúc do bị gọi exit
Khi thực hiện truyền đối số thành công, các chương trình người dùng sẽ được thực hiện
đúng cách và kết thúc bằng cách gọi exit() trong phần process_exit().
Để lấy được tên chương trình cần tạo một hàm phân tích cú pháp chuỗi đối số truyền vào
extract_command_name(fn_copy, cmd_name); sau đó chỉnh sửa hàm load() được gọi trong
start_process() với tên tệp đã được phân tích cú pháp khi chạy chương trình. Do chưa thực
hiện process_wait() nên tiến trình mẹ có thể sẽ kết thúc trước mà không đợi tiến trình con
3.4 Triển khai mã nguồn
Các hàm và các biến được triển khai trong file:
userprog/process.c và process.h
3.5 Sửa đổi mã nguồn và bổ sung
Các biến và hàm được thêm vào userprog/process.h:
o void process_exit (int status); o void
process_init(void);
Chỉnh sửa khung hàm được cấp sẵn: userprog/process.c:
• Thêm hàm static bool setup_stack() :cài đặt con trỏ ngăn xếp .
• Sửa đổi chức năng process_execute ()start_process()
• Sửa đổi chức năng process_wait ()process_exit(): Trong hàm process_wait vòng lặp
và process_exit để in ra khi tiến trình kết thúc.
• Thêm 2 hàm bool process_is_parent_of () void remove_child(): kiểm tra có phải tiến
trình mẹ hay không và xóa tiến trình con .
• Chỉnh sửa hàm load() , install_page()
• Thêm 2 hàm extract_command_name()extract_command_args()
• Thêm 2 hàm process_close_all()process_init() 3.6 Kết quả
Sau khi kiểm tra bằng lệnh make check thì đã pass:
Hình 6: Kết quả sau khi đã make check test termination message process
CHƯƠNG 4. KẾT LUẬN
Sau khi tìm hiểu và đưa ra giải pháp, vấn đề “Advanced Scheduler” trong Project 1 của
Pintos đã được giải quyết. Trong Project 2, nhóm em đã thực hiện Process Termination
Message . Về cơ bản đã được nhóm em kiểm tra và chạy thử nghiệm thành công. Sau khi kết
thúc môn học, và có nhiều thời gian hơn, chúng em sẽ có gắng dùng những kiến thức đã tính
luỹ từ môn học để hoàn thành các project còn lại trong dự án Pintos .
Chúng em xin chân thành cảm ơn thầy đã hướng dẫn chúng em để hoàn thành dự án này.
TÀI LIỆU THAM KHẢO
https://web.stanford.edu/~ouster/cgi-bin/cs140-spring20/pintos/pintos_2.html#SEC15
https://www.scs.stanford.edu/21wi-cs140/pintos/pintos_2.html
Hyperlink project: https://github.com/nghia3040khai2927duy2805/pintos_project.git