Một chút tìm hiểu về quá trình thực thi 1 hàm
- Xây dựng trong kernel space
Để xác định user đang gọi cái interrupt nào. Ta cho nó 1 định danh là 1 số nào đó. Khi kernel nhận được số đó thì hiểu là user yêu cầu chuyện gì.
Ví dụ: Nếu user đưa vô số 11 tức là yêu cầu đọc 1 số nguyên từ console. - Tạo macro:
Để đỡ phải quên trong việc lập trình, ta sẽ define số đó thành 1 macro.
Trong syscall.h:
define SC_ReadInt 11
Khai báo interface cho end-user:
Cũng trong syscall.h, ta tạo một hàm để người dùng (end-user) giao tiếp với hệ điều hành, ở đây ta khai báo hàm ReadInt();
int ReadInt();
Định nghĩa hàm trong file assembler.
Khi người dùng gửi đến 1 thông điệp, ví dụ như “đọc 1 số từ console”, đến với hệ điều hành – lúc này hiểu thông điệp là 11 chẳng hạn. Để hệ điều hành nhận được số 11 đó và truyền đến chỗ xử lý các thông điệp, ta cần pass giá trị này qua. Giống như gọi 1 hàmxxx(11)
vậy. Trong nachos, công việc này tức là truyền 11 vào biến $2 được qui định trước đó và gọi system call.
Ta mở các file sau: code/test/start.c và code/test/start.s:
.globl ReadInt .ent ReadInt ReadInt: addiu $2, $0, SC_ReadInt syscall j $31 .end ReadInt
Như vậy, thông điệp “đọc 1 số từ console” đã đến tai hệ điều hành. Giờ là lúc bắt tay vào xử lý công việc đó. Và vì đây là software interrupts, hay còn gọi là 1 exceptions. Nên dĩ nhiên, ta sẽ thêm mã vào file usrprog/exceptions.cc
///.... switch(which) { case SystemcallException: switch(type) { case SC_ReadInt: // Đoạn mã thực thi break; // Các xử lý khác ... } / Tăng biến pc lên 1 đơn vị machine->Registers[PrevPCReg] = machine->Registers[PCReg]; machine->Registers[PCReg] = machine->Registers[NextPCReg]; machine->Registers[NextPCReg] += 4; } ///....
- Một số lớp và phương thức được thêm vào trong đồ án:
- SynchConsole
Được cài đặt ở thư mục threads/ giúp truy xuất giữa console và người dùng.
Trong file threads/system.h, phần định nghĩa macro USER_PROGRAM ta include header file của SynchConsole. Đồng thời khai báo extern cho biến gSynchConsole;
Trong file threads/system.cc, cũng trong phần khai báo macro USER_PROGRAM ta khai báo biến gSynchConsole (chỉ khai báo, không có khóa extern).$ifdef USER_PROGRAM #include "synchcons.h" extern SynchConsole *gSynchConsole; #endif
- User2System và System2User
Mã code của 2 phương thức này được trình bày ở link này: Click vào đây
Hai hàm này sẽ trở thành phương thức public trong lớp Machine. Khai báo hàm nằm ở machine/machine.h và phần định nghĩa sẽ nằm ở machine/machine.cc hoặc có thể là trong translate.cc. Mình nghĩ là nên đặt vào trong translate.cc hơn, vì nó phần nào thể hiện bản chất: các phương thức liên quan đến vùng nhớ sẽ được đặt ở đó.
- SynchConsole
- Test hàm và chạy thử nghiệm
Trong thư mục test/, ta tạo một tập tin .c để kiểm tra tính đúng đắn của exception vừa viết. Đó là gọi hàm đó theo tham số đã đề xuất.
Cấu hình Makefile:
Để có thể sử dụng lớp SynchConsole, ta mở file Makefile.common và thêm các thông số sau:
- Tại THREAD_H : ‘../threads/synchcons.h’
- Tại THREAD_C : ‘../threads/synchcons.cc’
- Tại THREAD_O : ‘../threads/synchcons.o’
Cấu hình file test
Ví dụ ta muốn chạy đoạn mã test.c, qui trình biên dịch và chạy như sau: - Trong file test/Makefile:
all: ... test
Thêm vào cuối file
test.o: test.c $(CC) $(CFLAGS) -c test.c test: test.o test.o $(LD) $(LDFLAGS) start.o test.o -o test.coff ../bin/coff2noff test.coff test
Sau khimake
xong, ta chạy lệnh./usrprog/nachos -rs 1023 -x [Đường dẫn đến file thực thi]
.