Theo định nghĩa của Silberschatz "Hệ điều hành là chương trình quản lý phần cứng máy tính." Tuy nhiên, quan điểm về một hệ điều hành còn tùy thuộc nhiều vào nhu cầu và góc nhìn của người
Trang 1TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO ĐỒ ÁN MÔN HỌC
HỆ ĐIỀU HÀNH Lab02 : System callsGiảng viên lý thuyết : Thầy Trần Trung Dũng
Lớp: 21CNTN
THÀNH PHỐ HỒ CHÍ MINH, NGÀY 1 THÁNG 11 NĂM 2023
Trang 2Lời nói đầu
Hệ điều hành là một bài toán mở và không có một định nghĩa thật chuẩn xác Theo địnhnghĩa của Silberschatz "Hệ điều hành là chương trình quản lý phần cứng máy tính." Tuynhiên, quan điểm về một hệ điều hành còn tùy thuộc nhiều vào nhu cầu và góc nhìncủa người dùng và hệ thống Quan điểm thứ nhất cho rằng hệ điều hành là một bộ điềuphối tài nguyên Ở quan điểm này, hệ điều hành nắm giữ các tài nguyên, nó có nhiệm
vụ cấp phát và thu hồi các tài nguyên này cho người dùng luân phiên nhau
Hình 1: Một số hệ điều hành hiện nayTrong quan điểm thứ hai, hệ điều hành là một máy ảo Nghĩa là hệ điều hành cungcấp cho mỗi người dùng một máy ảo Máy ảo này có thể giống với máy tính vật lý thật,
có thể là một máy tính hoàn toàn khác, có thể là một máy tính mạnh hơn Điều quantrọng là máy ảo tạo cho người dùng tin rằng họ sỡ hữu riêng tài các tài nguyên phầncứng cần thiết cho nhu cầu của mình Một góc nhìn khác nữa là xem hệ điều hành nhưmột bộ giúp chia sẻ tài nguyên chung Hệ điều hành chịu trách nhiệm phân chia, phòngchống xâm phạm tài nguyên giữa các người dùng Đồng thời quản lý sự cộng tác củangười dùng trong việc sử dụng chung nguồn tài nguyên hạn hẹp Đây cũng là góc nhìnkinh tế, vì chúng ta không thể mua sắm hết tất cả các tài nguyên cần thiết
Với đồ án này, nhóm em tiến hành thực hiện trên Hệ điều hànhUbuntu Bài tập đãđược hoàn thiện đầy đủ và báo cáo chi tiết ở các phần sau
Trang 3Mục lục
2.1 Cài đặt môi trường 5
2.2 Kiểm tra cài đặt 5
3 Thực hiện đồ án 6 3.1 Using gdb 6
3.1.1 Thực hiện cài đặt theo yêu cầu 6
3.1.2 Trả lời các câu hỏi của đề bài 6
3.2 System call tracing 11
3.2.1 Thực hiện cài đặt 11
3.2.2 Build và run 15
3.2.3 Testing 16
3.3 Sysinfo 16
3.3.1 Thực hiện cài đặt: 16
3.3.2 Build and Run: 21
3.3.3 Kiểm tra: 21
3.3.4 Test toàn bộ bài tập 21
4 Phân công công việc của các thành viên 22 5 Tài liệu tham khảo 22 Danh sách hình vẽ 1 Một số hệ điều hành hiện nay 1
2 Xv6 4
3 Cài đặt Xv6 - labs - 2023 trên Ubuntu 5
4 Kiểm tra cài đặt trên Ubuntu 5
5 Các bước thực hiện yêu cầu bài tập 6
6 Kết quả trả về sau khi thực hiện 7
7 Number syscall lưu trữ trong thanh ghi a7 8
8 Kết quả kiểm thử bài tập Lab02 21
Danh sách bảng 1 Bảng phân công thành viên 22
Trang 4Thông tin chung về đồ án học tập
Môi trường phát triển: Hệ điều hành Ubuntu
Thông tin chi tiết:
•Project được giao trong link
•Báo cáo về đồ án
Lời cảm ơn
Những kiến thức về môn họcHệ Điều Hànhđược ứng dụng trong đồ án của chúng
em được thầyTrần Trung Dũng, Lê Giang Thanh, Nguyễn Thanh Quân giảngdạy rất nhiệt tình, tâm huyết Chúng em xin cảm ơn các thầy vì đồ án này nói riêng và
vì những kiến thức mà các thầy đã cung cấp nói chung
Ngoài ra, nhóm cũng đã tham khảo từ nhiều trang web như GitHub và trang webchính thứcXv6 Những thuật toán, những ý kiến giải đáp trên các diễn đàn trên đãgóp phần giúp nhóm thực hiện đồ án này
Thành phố Hồ Chí Minh, ngày 14 tháng 10 năm 2023
Trang 51 Giới thiệu về Xv6
Xv6 là một khóa học hệ điều hành phát triển vào mùa hè năm 2006 Xv6 là một hệ điềuhành thí nghiệm mã nguồn mở dựa trên Unix, được phát triển tại Đại học MIT Nóđược thiết kế nhằm mục đích giáo dục và nghiên cứu về hệ điều hành, giúp sinh viên vànhà nghiên cứu hiểu rõ hơn về cấu trúc và hoạt động của một hệ điều hành
Xv6 được xây dựng dựa trên hệ điều hành Unix V6 của Bell Labs, một trong nhữngphiên bản Unix ban đầu Nó được viết bằng ngôn ngữ C và mã nguồn của nó có thểđược tìm thấy trên GitHub để mọi người có thể tìm hiểu và đóng góp vào dự án.Mục tiêu chính của Xv6 là cung cấp một hệ điều hành đơn giản, nhẹ và dễ hiểu Nóbao gồm một số tính năng cơ bản của hệ điều hành như quản lý tiến trình, bộ nhớ, tệptin và giao tiếp qua hệ thống Xv6 cung cấp một giao diện dòng lệnh đơn giản cho ngườidùng và hỗ trợ một số lệnh cơ bản như ls, cat, rm và cp
Xv6 đã được sử dụng rộng rãi trong các khóa học về hệ điều hành và nghiên cứu tạinhiều trường đại học trên thế giới Việc nắm vững và tìm hiểu về Xv6 có thể giúp sinhviên và nhà nghiên cứu hiểu sâu hơn về cách hoạt động của hệ điều hành và phát triển
kỹ năng lập trình hệ thống Chi tiết có thể tìm thấy trong link sau : Xv6
Hình 2: Xv6
Trang 62 Mô tả cụ thể
2.1 Cài đặt môi trường.
Trước khi vào bài tập, chúng ta cần phải cài đặt môi trường và các thư viện cần thiếtcho đồ án Phần cài đặt này có thể tìm thấy trong phần Tools Used, tùy vào hệ điềuhành đang sử dụng mà có các cài đặt khác nhau Ở đây nhóm chúng em sử dụng hệđiều hànhUbuntu
Hình 3: Cài đặt Xv6 - labs - 2023 trên Ubuntu
2.2 Kiểm tra cài đặt
Sau khi tiến hành, cài đặt thành công môi trường, các phiên bản củaQEMU, GNU, Sau
đó, chúng em tiến hành kiểm thử và và bắt đầu thực hiện đồ án
Hình 4: Kiểm tra cài đặt trên Ubuntu
Trang 73 Thực hiện đồ án
3.1 Using gdb
Bài tập này giúp tìm hiểu cách hoạt động và cách sử dụng gdb Giống vớiLab1, thầy
Lê Giang Thanh đã giới thiệu
3.1.1 Thực hiện cài đặt theo yêu cầu
Hình 5: Các bước thực hiện yêu cầu bài tập
Kết quả sau khi thực hiện đầy đủ các lệnh trên được mô tả trong hình 6:
3.1.2 Trả lời các câu hỏi của đề bài
Câu trả lời được lưu trữ trong file answers-syscall.txt
Question : Looking at the backtrace output, which function called syscall?Trả lời : Kết quả cho biết syscall được gọi bởiusertrap, nó được chỉ ra trongoutput củabacktrace
Trang 8Hình 6: Kết quả trả về sau khi thực hiện.
Trang 9Question : What is the value of p->trapframe->a7 and what does thatvalue represent? (Hint: look user/initcode.S, the first user program xv6starts.)?
Chúng em đã thực hiện gõ n 2 lần để giúp chostruct proc *p = myproc()có thểthực thi Sau đó gỡ lệnhp /x *pvà xem kết quả
Thực hiện kiểm tra giá trịp->trapframe->a7 Kết quả đầu ra như sau :(gdb) p p->trapframe->a7
Trang 10Trong bài này, number syscall là 15, dựa vào filekernel/syscall.h thì number syscallnày đại diện choSYS_exec.
// System call numbers
#define SYS_fork 1 #define SYS_dup 10
#define SYS_exit 2 #define SYS_dup 10
#define SYS_wait 3 #define SYS_sbrk 12
#define SYS_pipe 4 #define SYS_sleep 13
#define SYS_read 5 #define SYS_uptime 14
#define SYS_kill 6 #define SYS_open 15
#define SYS_exec 7 #define SYS_write 16
#define SYS_fstat 8 #define SYS_mknod 17
#define SYS_chdir 9 #define SYS_unlink 18
#define SYS_link 19 #define SYS_mkdir 20
Như chúng ta có thể thấy, giá trị của bit SPP là 0, cho biết mức đặc quyền trước khivào kernel cho lệnh gọi hệ thống là user mode
Khi thực hiện sửa câu lệnhnum = p->trapframe->a7; thành câu lệnh khác
Trang 11sepc cho biết địa chỉ của mã nơi mà kernel gặp sự cố Chúng ta có thể tìm kiếm mãnày trongkernel/ kernel.asm.
num = * (int *) 0;
8000204e: 00002683 lw a3, (zero) #0 0 <_entry-0x80000000>
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
Dựa vào đoạn code trên ta có thể thấy, chính sự thay thế câu lệnh đã gây ra lỗi chokernel và tương ứng cho lệnh lỗi này trong assembly làlw a3,0(zero)
Question : Why does the kernel crash? Hint: look at figure 3-3 in the text;
is address 0 mapped in the kernel address space? Is that confirmed by thevalue in scause above? (See description of scause in RISC-V privileged in-structions)
Thread 2 hit Breakpoint 1, syscall () at kernel/syscall.c:126
Nếu chúng ta nhập vào n thì panic sẽ diễn ra một lần nữa Do đó, chúng ta có thểchấm dứt quá trình và kiểm tra giá trị của thanh ghi scause bằng cách:
p $scause
$4 = 13
Theo hướng dẫn của RISC-V, giá trị 13 ở đây biểu thị lỗi trang tải Đặc biệt, đã xảy
ra lỗi khi tải dữ liệu từ địa chỉ bộ nhớ 0 vào s2 Như chúng ta có thể thấy trong sáchgiáo trình, địa chỉ 0 không ánh xạ tới không gian kernel; đúng hơn, nó bắt đầu ở địa chỉ
ảo 0x80000000
Question : What is the name of the binary that was running when thekernel paniced? What is its process id (pid)?
Trang 12(gdb) p *p
$2 = {lock = {locked = 1, name = 0x800081b8 "proc", cpu = 0x80008a50
<cpus+256>}, state = RUNNING, chan = 0x0, killed = 0, xstate = 0, pid = 1,parent = 0x0, kstack = 274877894656, sz = 4096, pagetable = 0x87f73000,trapframe = 0x87f74000, context = {ra = 2147488960, sp = 274877898352, s0
= 274877898400, s1 = 2147519824, s2 = 2147518752, s3 = 1, s4 =
274877898448, s5 = 2147544024, s6 = 3, s7 = 2147588592, s8 = 1, s9 =
2147588888, s10 = 4, s11 = 0}, ofile = {0x0 <repeats 16 times>}, cwd =0x80016e60 <itable+24>, name = "initcode\000\000\000\000\000\000\000"}
Khi đó chúng ta có thể thấy rằng pid của initcode là 1
3.2 System call tracing
Đề bài: Trong bài tập này, chúng sẽ thêm tính năng theo dõi cuộc gọi hệ thống có thểgiúp bạn khi gỡ lỗi trong các labs sau này Bạn sẽ tạo lệnh gọi trace system mới để kiểmsoát việc tracing Nó phải lấy một đối số, một number mask, có các bit chỉ định lệnh gọisystem call nào để trace Ví dụ: để trace system call fork, một chương trình gọi trace(1
« SYS_fork), trong đó SYS_fork là số hệ thống từ kernel/syscall.h Bạn phải sửa đổitrong kernel xv6 để in ra một dòng khi mỗi systemcall sắp quay trở lại, nếu systemcall’number được đặt trong mask Dòng này phải chứa process id, tên của system call
và giá trị trả về; bạn không cần in các đối số của system call Lệnh trace system call sẽcho phép theo dõi tiến trình gọi nó và bất kỳ tiến trình con nào mà nó phân nhánh sau
đó, nhưng không ảnh hưởng đến các tiến trình khác
3.2.1 Thực hiện cài đặt
Dựa vào các gợi ý của đề bài, nhóm chúng em thực hiện theo các bước sau:
•Thêm prototype cho system call vào fileuser/user.h Thêm một stub vào fileuser/usys.pl và một syscall number vào file kernel/syscall.h
Trang 13Sau đó khai báo$U/_ trace vào phầnUPROGS trong Makefile.
// user/user.h
// system calls
int sleep( );int
int uptime(void);
int trace( );int
// kernel/proc.h
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
uint64 syscall_trace;
Mặc dùsys_tracecó thể được định vị trong bất kỳ tệp nào, nhưng việc đặt nótrongkernel/sysproc.c sẽ đơn giản hóa việc phân loại
Trang 14extern uint64 sys_mkdir(void);
extern uint64 sys_close(void);
extern uint64 sys_trace(void);
Trang 15num = p->trapframe->a7; // syscall number in a7
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {// Use num to lookup the system call function for num, call it,// and store its return value in p->trapframe->a0
p->trapframe->a0 = syscalls[num]();
// trace
if (p->syscall_trace & (1 << num)) {
printf("%d: syscall %s -> %d\n", p->pid, syscall_names[num],p->trapframe->a0);
}
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);
p->trapframe->a0 = -1;
}
}
Trang 16ALL TESTS PASSED
Kết quả thông báo toàn bộ tests đã pass tại dòngALL TESTS PASSED
Trang 17trace all grep: OK (0.9s)
== Test trace nothing ==
Trang 18int sleep( );int
int uptime(void);
int trace( );int
int sysinfo(struct sysinfo*); //prototype of sysinfo
- Tiếp đó, để khi gọi hàm sysinfo trong user space thì một system được kích hoạtthì ta phải thêm một entry tương ứng vớisysinfotrong fileuser/usys.pl
Trang 19- Sau đó trong kernel/syscall.h chúng ta thêm prototype của hàm mà handle systemcall này (chúng ta đặt tên nó làsys_sysinfo), và kết nối hàm này với số đã đượcđịnh nghĩa tương ứng với system callsysinfođể kernel có thể xử lý được.
//kernel/syscall.c
// Prototypes for the functions that handle system calls
extern uint64 sys_mkdir(void);
extern uint64 sys_close(void);
extern uint64 sys_trace(void);
extern uint64 sys_sysinfo(void);
// An array mapping syscall numbers from syscall.h
// to the function that handles the system call
static uint64 (*syscalls[])(void) = {
có thể thấy và dùng được nó thì ta phải thêm prototype của hàm này vào trongkernel/defs.h
//kernel/defs.h
// proc.c
void procdump(void);
int sysinfo(uint64 addr);
Trang 20int
sysinfo(uint64 addr){
struct proc *p = myproc();
struct sysinfo info;
nó bằng việc gọi các hàmget_freemem() để lấy số byte đang không được dùngtrong bộ nhớ chính vàget_nproc()để lấy số tiến trình đang không ở trong trạngthái UNUSED Hàmget_freemem()được định nghĩa ởkernel/kalloc.c và hàmget_nproc() được định nghĩa ở chính kernel/proc.c
- Sau đó ta thực hiện copyout(p->pagetable, addr, (char *)&info, sizeof(info)) < 0
để đẩy dữ liệu từ kernel space về user space ở đúng địa chỉ mà người dùng đangmuốn lấy dữ liệu
- Với hàm get_freemem() được định nghĩa ở kernel/kalloc.c, nó sẽ trả về số byteđang không được dùng trong bộ nhớ chính và được cài đặt như sau:
Trang 21- Với hàm get_nproc() được định nghĩa ở kernel/proc.c, nó sẽ trả về số tiến trìnhđang không ở trong trạng thái UNUSED và được cài đặt như sau:
Trang 223.3.2 Build and Run:
Thực hiệnmake qemu để build chương trình và thực hiện lệnhsysinfotest, chúng em
có kết quả như sau:
root@NQB:~/xv6-labs-2023# /grade-lab-syscall sysinfo
make: 'kernel/kernel'is up to date
== Test sysinfotest == sysinfotest: OK (5.3s)
Kết quả cho thấy chúng em đã hoàn thành đúng yêu cầu của bài tập
3.3.4 Test toàn bộ bài tập
Sử dụng lệnhmake grade để chạy test cho tất cả bài tập nhóm chúng em được kếtquả minh họa trong hình 8
Hình 8: Kết quả kiểm thử bài tập Lab02
Trang 234 Phân công công việc của các thành viên
Bảng 1 dưới đây mô tả thông tin phân công các thành viên của nhóm
Tô Tấn Hiệp
•Thực hiện bài tập Using gdb
•Thực hiện bài tập System call tracing
•Viết Report
100
Ninh Quốc Bảo
•Thực hiện bài tập Sysinfo
•Viết Report
100
Bảng 1: Bảng phân công thành viên
5 Tài liệu tham khảo
•Giáo trình Hệ Điều Hành Khoa Công Nghệ Thông Tin, trường Đại Học Khoa Học
Tự Nhiên - ĐHQG TP Hồ Chí Minh
•Slide bài giảng môn học Hệ Điều Hành của thầy Trần Trung Dũng
•Sách tham khảo vềXv6được cung cấp trên moodle