ExitUpdatein ec cua tién trinh dang chay Output: exit code cuối cùng của tiên trình đây Chức năng: Cho phép kết thúc quá trỉnh Join của | tién trinh khi no da chay xong Được cung câp bởi
BitMapn
Để theo dõi các tiến trình hiện hành, chúng ta sẽ sử dụng BitMap để quản lý việc cấp phát, hủy cấp phát và thực hiện một số thao tác khác như tìm kiếm và thêm tiến trình mới vào hệ thống đa chương trong Nachos Trong đồ án này, BitMap sẽ được thể hiện qua hai cách khác nhau.
- _ Thuộc tính 8#⁄ap* bm của PTable pTab (đã đề cập ở PTable)
The local BitMap variable, physicalPage, is defined in six files within the system, specifically in "ip" and "system.cc." This variable is utilized to interact with AddrSpace in the Thread class and is essential for managing physical memory pages in Nachos.
Lớp BitMap được khai báo và cài dat lần lượt ở BitMap.h va BitMap.cc
Dưới đây là thông tin của lớp BitMap:
Tên Loại Kiều dữ liệu Nội dung Ghi chú
BitsInByte Hằng số Số bit trong Được cung cấp một byte của bởi giáo viên Nachos
BitsInWord Hang so So bit trong Được cung cấp một word của | bởi giáo viên Nachos
BitMap(mt Constructor BitMap Phương thức Được cung cấp nitems) khoi tao cho bởi giáo viên
BitMap, với nitems chính là số bit mà
Destructor của BitMap là phương thức huỷ được cung cấp bởi giáo viên Thuộc tính numBits là số lượng bit mà BitMap phải quản lý, trong khi thuộc tính numWords là số lượng word được tính từ numBits.
NumWords ceil(numBits/B itsInWord) Được cung câp bởi giáo viên map Thuộc tính unsigned int* Dé quan lý các bit higu qua nhất, thì
BitMap sẽ quản lý các từ đôi được sinh ra từ các Bit Danh sách các từ mà BitMap quản lý sẽ được cung cấp bởi giáo viên Phương thức void Input sẽ nhận vị trí bit mà chúng ta muốn đánh dấu, trong khi Output không có kết quả cụ thể.
Chức năng: danh dau 1 bit
0 vi tri which, có ý nghĩa rằng bit nay đã bị sử dụng
Phương thức void Input: vi tri bit ta muốn bỏ đánh đầu
Output: không có Chức năng: bỏ danh dau 1 bit
0 vi tri which, có ý nghĩa ngược lại với Mark(mt which) Được cung câp bởi giáo viên
Phương thức bool Input: vị trí mà bit mà ta muốn kiêm tra Output:
- True néubit 6 vi tri nay da bi danh dau Được cung câp bởi giáo viên
- False nếu ngược lại Chức năng:
Kiểm tra | bit ở vị trí bất kì, để biết rằng nó có bị đánh dấu hay chưa
FindQ Phương thức mt Input: không có
Output: vi trí của | bit chưa bi danh dau
Chirc nang: tim kiếm | vi tri bit trong, chua bi đánh dâu của BitMap Được cung câp bởi giáo viên
Phương thức int Input: không có
Số lượng các bit chưa bị đánh dấu trong BitMap được cung cấp bởi giáo viên Chức năng này giúp đếm số lượng các bit con chưa được đánh dấu trong hệ thống.
Print() Phương thức void Input: không có
Output: không có Chức năng: m ra màn hình các vị tri bit da danh dau Được cung câp bởi giáo viên
Phương thức void Input: file muốn đọc đữ liệu từ BitMap Output: không có Chức năng: nạp đữ liệu từ BitMap vao | file Được cung câp bởi giáo viên
Phương thức void Input: file muốn ghi đữ liệu vào BitMap Output: không có Chức năng: ghi dit ligu tir file vao BitMap Được cung câp bởi giáo viên
Trong hệ thống Nachos, mỗi tiến trình được gọi và quản lý bởi một thread duy nhất, đảm nhiệm việc khởi chạy và kết thúc các tiến trình Các thread này không chỉ quản lý trạng thái của tiến trình mà còn có khả năng điều phối thứ tự thực thi, ví dụ như yêu cầu tiến trình A phải chờ tiến trình B Trong dự án này, thread được triển khai với bốn thể hiện khác nhau.
- _ Thuộc tính 7zead* thread của thuộc tính Bi/A4ap* bm nam trong PTable pTab (đã đề cập ở PTable)
- _ Thuộc tính 7hread* thread của biễn cục bộ BitMap* physicalPage được khai bảo ở file system.h va system.cc
- Bién cuc b6 Thread* currentThread duoc khai bao o file system.h va system.cc
- Biến cục bộ Thread* threadToBeDestroyed được khai báo ở file system.h và system ce
Lớp Thread được khai báo và cài đặt lần lượt ở /#read.h và thread.cc
Dưới day la thong tin cla lop Thread
Tén Loai Kiêu dữ liệu Nội dung Ghi chú
MachineStateSi | Hang s6 Kích thước của | Được cung cấp ze mảng đề lưu bởi giáo viên trữ trạng thái thanh ghi CPU
Kích thước ngăn xếp (StackSize) là kích thước của ngăn xếp mà mỗi thread được tạo ra sử dụng để thực thi các tiến trình mà thread đó quản lý Enum ThreadStatus cung cấp các trạng thái khác nhau của thread.
BLOCKED stackTop Thuộc tính int* Stack pointer cua Thread hién tai Được cung câp bởi giáo viên machmeState[
Thuộc tính int Máng lưu trữ các trạng thái thanh ghi của CPU cho mỗi thread Được cung câp bởi giáo viên
Constructor Thread Phương thức khởi tạo cho Thread, trong đó threadName chính là tên của Thread mà người dùng muôn đặt Được cung câp bởi giáo viên
Phương thức hủy của Thread, gọi là ~Thread(), được cung cấp bởi giáo viên Thuộc tính processID là ID kiểu int của tiến trình mà thread đang quản lý, cũng được cung cấp bởi giáo viên.
Fork(VoidFunc Phương thức void Input: hàm mà Được cung cập
2ó tionPtr func, int arg) người dùng muốn khởi chạy và các tham số của hàm đó Output: không có Chức năng:
Khởi tạo các thông tin cần thiết cho mộ tiêu trình, sau đó khởi chạy nó bởi giáo viên
Yield() Phương thức void Input: không có
Output: không có Chức năng:
Nhường CPU cho | thread muốn được chạy Được cung câp bởi giáo viên
SleepQ Phương thức void Input: không có
Output: không có Chức năng:
Nhường CPU Được cung câp bởi giáo viên
27 de dura thread hién tai vao trang thai ngu vi thread nay hiện dang bi blocked
Finish() Phương thức void Input: không có
Output: không có Chức năng: kết thúc tiền trình của thread hiện hành Được cung câp bởi giáo viên
Phương thức void Input: không có
Output: không có Chức năng:
Kiểm tra xem stack của thread có bị tràn hay không Được cung câp bởi giáo viên setStatus(Threa dStatus st) Phương thức void Input: không có
Output: không có Chức năng: setter cho thuộc Được cung câp bởi giáo viên
28 tính status getName() Phương thức char* Input: không có | Được cung câp
Output: không | bởi giáo viên có Chức năng: getter cho thuộc tính name
Print() Phương thức void Input: không có | Được cung câp
Trong bài viết này, chúng ta sẽ khám phá các thuộc tính và chức năng của thread trong lập trình Đầu tiên, thuộc tính "Stack" cho phép hiển thị tên của thread trên màn hình Tiếp theo, thuộc tính "ThreadStatus" cung cấp thông tin về trạng thái hiện tại của thread mà giáo viên đang quản lý Chúng ta cũng sẽ tìm hiểu về thuộc tính "name", cho biết tên của thread, và phương thức "userRegisters", cho phép truy cập vào các thanh ghi liên quan đến thread.
NumTotalRegs đành cho bởi giáo viên
29 thread khi phải thực thi user code
ThreadFinish() Phương thức tinh void Input: không có
Output: không có Chức năng: don rac cho bién toan cuc currentThread Được thêm vào
Phương thức void Input: không có
Output: không có Chức năng: lưu lại trạng thái các thanh ghi của machine vào userRegisters Được cung câp bởi giáo viên
RestoreUserSta teQ) Phương thức void Input: không có
Output: không có Chức năng: ghi lại trạng thái các thanh ghi của machine băng với các Được cung câp bởi giáo viên
30 thanh ghi userRegisters space Thuộc tính AddrSpace* Vùng nhớuser | Được cung cấp cho thread bởi giáo viên
Cac system call mà nhóm can cai đặt thêm vào
Exec là một system call cho phép Nachos thực thi bất kỳ chương trình nào Để cài đặt Exec, trước tiên cần thiết lập để Nachos hiểu cách gọi system call này Sau đó, nhóm sẽ tiến hành cài đặt system call, với mã giả được sử dụng để thực hiện quá trình này.
Exec nhận tham số là tên của tiến trình cần khởi chạy Để lấy tên tiến trình, ta đọc địa chỉ của mảng tên tại thanh ghi R4 và sau đó đọc vùng nhớ với kích thước MAX BUFFER LENGTH + 1 (255) Vùng nhớ này sẽ được chuyển từ User sang System, lúc này processName sẽ chứa tên của tiến trình cần khởi chạy.
Nếu không đọc được tên của tiền trình => Exec lập tức báo lỗi, trả về -I (bằng cách ghi vào thanh ghi R2 gia tri -1), và kết thúc systemcall
Ngược lại, ta nạp tên của tiễn trình cần chạy (processID) vào phương thức
Hàm ExecUpdate(char*) thuộc lớp PTable và được giải thích trong bảng trên, có vai trò khởi chạy tiến trình với tên đã được nạp vào Biến toàn cục PTable* pTab được định nghĩa trong file system.h Sau khi thực hiện xong, ExecUpdate sẽ trả về giá trị là process ID của tiến trình, và giá trị này sẽ được lưu vào biến pid.
Biến pid chính là giá trị trả về của system call Exec Ta trả về kết quả là pid bằng cách ghi vào thanh ghi R2 giá trị pid
Trước khi hoàn tất hoàn toàn system call, chúng ta cần tăng biến đếm program counter của Nachos để tiếp tục thực hiện lệnh tiếp theo Sau đó, quá trình xử lý của Exec sẽ được kết thúc.
Hàm Join là một system call cho phép một tiến trình phải chờ cho đến khi tiến trình khác hoàn thành trước khi tiếp tục thực hiện Join thường được sử dụng kết hợp với system call Exit Để Nachos có thể nhận diện cách gọi này, cần phải thiết lập hệ thống phù hợp Nhóm sẽ tiến hành cài đặt system call Join với mã giả tương ứng.
Hệ thống gọi Jom nhận vào process ID của tiến trình con mà tiến trình cha cần chờ đợi Để lấy process ID này, chương trình chỉ cần đọc giá trị từ thanh ghi R4 và gán giá trị đó vào biến pid.
EX
Khi một tiến trình cha kết hợp với tiến trình con, nếu tiến trình con hoàn thành mà không có system call Exit, Nachos sẽ không trả lại CPU cho tiến trình cha và sẽ dừng hoạt động Để khắc phục tình trạng này, cần phải triển khai system call Exit.
Hệ thống gọi "exit" cho phép tiến trình con kết thúc và nhường CPU cho tiến trình cha tiếp tục thực thi Để sử dụng hệ thống gọi này, trước tiên cần thiết lập để Nachos có thể nhận diện cách gọi Nhóm sẽ tiến hành cài đặt hệ thống gọi này, đây là mã giả:
Hệ thống gọi Exit nhận mã thoát (exit code) của tiến trình từ hệ thống gọi Join Chương trình sau đó lưu giá trị mã thoát này vào thanh ghi R4 và gán giá trị đó cho biến jomExitCode.
Khi quá trình Join diễn ra mà không gặp lỗi, hệ thống sẽ trả về mã thoát (exit code) là 0 Nếu giá trị JoinExitCode nhận được khác 0, điều đó cho thấy đã xảy ra lỗi Trong tình huống này, chương trình sẽ tăng biến đếm program counter và kết thúc chương trình.
Nếu không có lỗi xảy ra từ Join, chương trình sẽ truyền giá trị joinExitCode vào phương thức ExitUpdate(nt) của biến toàn cục pTab, được định nghĩa dưới dạng PTable* trong file system.h.
Tiếp theo, chương trình thực hiện dọn rác cho biến toàn cục currentThread bằng cách gọi phương thức tĩnh ThreadFInish(), mà nhóm đã cài đặt
Vì system call Exit không có giá trị trả về, chương trình chỉ đơn giản là tăng biến đếm program counter lên và kết thúc
Các chỉnh sửa đã thực hiện ở source code
1 Khai báo các biên toàn cục mới ở system.h/system.cc
Ta có tông cộng thêm 3 biên toàn cục mới so với do an 2:
- Semaphore* addrLock: semaphore cho việc truy cập vào thao tác với các lớp AddrSpace
- PTable* pTab: ptable cho việc quản lý toàn bộ các tiên trình đa chương trong đồ án 3
- BitMap* physicalPage: cho viéc quan ly cac frame bé nhé trén nachos (phéi hợp với lớp AddrSpace)
Ta tiền hành khai báo các biến toàn cục mới này trong Region #USER PROGRAM nằm trong system.h/system.cc Đây là vị trí khai báo ở system.h
35 Đây là vị trí forward declaration 6 system.cc
Và vị trí khởi tạo
- Ta khởi tạo pTab với khả năng quản lý tối đa 10 tiễn trình (giá trị của
- Ta khởi tạo physIcalPage với kích thước bitmap quan lý là 256 bít
- Ta khởi tạo addrLock là semaphore với ten la addrLock, giá trị khởi tạo ban đầu là 1
Lớp BitMap cung cấp phương thức FindQ) cho phép tìm kiếm và đánh dấu các vị trí bit còn trống Chúng ta có thể dễ dàng tận dụng phương thức này thông qua phương thức ExecUpdate(char* filename).
Sau khi áp dụng phương thức FindQ của lớp BitMap, việc gọi hàm Mark() trong BitMap trở nên thừa thãi, vì FindQ đã tự động thực hiện chức năng đánh dấu Do đó, chúng ta có thể loại bỏ lệnh Mark() hiện có trong phương thức ExecUpdate().
Theo yêu cầu của đề bài, chúng ta cần thêm thông tin về processID thuộc tiến trình cha của tiến trình hiện hành bằng cách sử dụng lệnh: peb[ID]->parentID = currentThread->processID;
Như vậy ta chỉ thay duy nhất đoạn cuối cùng của phương thức ExecUpdate(char* filename), va no sé tro thanh: c Phương thức ExitUpdate(mt ec)
Chi tiết quan trọng trong phương thức này là ở đoạn cuối luôn thực hiện lệnh exit join, vì phương thức này chỉ được gọi từ hệ thống thông qua lệnh Exit Để lệnh Exit có thể chạy, cần phải có ít nhất một tiến trình đang hoạt động.
Việc kiểm tra tiến trình cha khi sử dụng hàm join trong lập trình là không cần thiết, vì khi đã vào đoạn mã này, tiến trình cha sẽ phải thoát ra Nếu không thoát, hệ thống sẽ dừng lại ngay lập tức, trong khi tiến trình cha vẫn chưa hoàn thành.
Ta thay đôi đoạn code cuối như sau:
Chuyén tir AddrSpace::AddrSpace(OpenFile* executable) thanh
Để giải quyết sự bất đồng bộ trong cách gọi constructor được cung cấp bởi giáo viên, nhóm đã quyết định sử dụng constructor AddrSpace::AddrSpace(char* filename).
Để đảm bảo truy xuất độc quyền trong constructor, cần thiết lập Semaphore addrLock và thêm đoạn mã addrLock->PQ cùng addrLock->V() ở cuối constructor.
Dưới đây là hướng dẫn xử lý cho constructor mới tương tự như constructor cũ, nghĩa là sau khi xử lý xong, logic mã ở phía bên trong cả hai constructor sẽ giống nhau.
Tiếp theo, chúng ta cần kiểm tra xem biến numPages có lớn hơn số trang còn trống hay không, như yêu cầu của đề bài Để xác định số trang còn trống, ta có thể sử dụng phương thức NưmClear() từ lớp BitMap, mà đã được khai báo toàn cục trong file system.h/system.cc Do đó, đoạn mã kiểm tra sẽ được viết như sau:
Để khởi tạo không gian địa chỉ cho tiến trình, cần thay thế `page Table[i].physicalPage = ¡` bằng hàm tìm trang trống đã sử dụng Hàm này chính là phương thức `Find(Q)` của lớp `BitMap`, cụ thể là `Find(Q)` của `physicalPage`.
Cuôi cùng, ta thay đôi cách nachos chuyên data segment vé memory nhu sau:
39 noffH code size noffH code virtuaLAddr, noffH.code.size executabLe machine->mainMemory [noffH code virtualAddr noffH code inFileAddr noffH.initData.size
%X %qd noffH.initData.virtualAddr, noffH.initData size executable machine mainMemory[noffH initData virtuatAddr noffH.initData inFileAddr
Do ta đã thêm vào sự xuất hiện của physicalPage khi phối hợp làm việc với AddrSpace
=> ta cần phải thu hồi bộ nhớ của cả physicalPage
Machine
a Thay đôi giá trị hằng số NumPhysPages
Ta thay đôi giá trị cũ thành 128
7 Disk a Thay đôi giá trị hằng số SectorSize
Ta thay đôi giá trị cũ thành 512
Chạy thử chương trình Scheduler
1 Chương trình scheduler Đầu tiên, nhóm xin phép được viết lại chương trình scheduler như sau (không còn giống trong slide)
Nhóm đã thêm vào lệnh gọi hệ thống Join để chương trình scheduler có thể chờ cả hai chương trình Ping và Pong hoàn tất trước khi tiếp tục thực hiện.
Khi gia nhập vào chương trình, nếu một trong hai chương trình Ping hoặc Pong hoàn thành trước, Nachos sẽ ngay lập tức dừng lại, trong khi scheduler vẫn chưa hoàn tất tất cả các tác vụ.
Ta không cần phải call system call Exit, vi ngay sau khi Join xong, Nachos sé tự động call system call Exit cho ta
Để xác nhận chương trình Scheduler hoạt động thành công, cả hai tiêu trình Ping và Pong phải hoàn thành Khi đó, dòng chữ “Finish Ping-Pong test” sẽ xuất hiện ở cuối console trước khi Nachos dừng lại.
Không có gì thay đôi so với yêu câu đề bài
Trên màn hình console, ta browse đến folder nachos/nachos-3.4/code/test (folđer chứa scheduler), sau day nhân lệnh sau:
.userprog/nachos -rs 1023 —x /test/scheduler
Ta sẽ ra được kết quả như đưới đây
44 test@test-virtual-machine:~/Desktop/21127168_21127247_21127580/Source/nachos/nachos-3.4/code$ /userprog/nach os -rs 1023 -x /test/scheduler
AAAAAAAAABBBBBBBBBBBBBBAAAAAABBBBBBBAABBBAAABBBAABAABBBAAAAAABBAAAAAAAABBBBBAAAABAABBBABAABBBBBBBBABAABAABBBB BBBBBAABBBBBAAABBBBBBBBBBBBBBBBBAAABAAABAAAAABBBBBBAABBBBBBBBAAAAAABBBABAABAAABBAAAAABAAAAAABBBAABBBBBAAABABB BBAAABABBBBAAAABBBAAAABAAAAAAAAAAAABBBBBAAAAABBBABBBBBAAABBBBAAAAAABBBBBBBBAABBBBBBBBBBBBBBBAABAABBBBAAAAABBA AAABBBBBBBABBAAAAABBBBBBBBBABABBAAAAABBBBBAAABAAAAAAABBBAABBBABBBBBBBBBBBAAABAAABABBBBBBBBBBAABBAAAAABBBBBBBB BAABBBAAAAAAAAABAABAAAABBAABBBAAABBBBBAAAAAABBBBBBBBAABBBBABBBBAAAAAAAAAAABBAAAAABBAAABBBBBAABBBBBBBBAAAAAAAA AAABBBBBBAAAAAAAAAAABBBAAAAAAABBBAAAAAAABBBBBBBBBBBAAAABBAAAAABBAABBBBAAAAAABBBBBBBAABBBBAABBBBBBBBBBBAABBBAA BAAAAAAABBAAAAAAAABBAAAABBBBBBBBAAAAAAAABBABBAABBBBBBBBBBBBAAAABAAAAAAAAABBBBBAAAABBBBBAAAABBAAAABAAAABABBBBA AAAAAAABBBABBBBBBBBBAAABAAAABAAABBBABBBBBBBBBBBBBBAABBBBBBAAAAABBBBAABBBBBBBBBBBBBBBBBBBBAAAAAAAAAABBBBBBBAAB BBBBBAABBBBBBAAABBBBBBBBBBBBBBBAAAABBBBBAAAAAABBBBBBABBBBBAAAAAAAABBBBBBBBBBBBBBBBBBBBBAAAAABBBBAAAAAAABBAABA AABABBAAAAABBBBABAABBBBBBBBABBBBAAAAABBBBBAABBBBBBBABBAABBBBBBBBAAAABBBBAAABBBBAAAAAAAABAABBBBAAAABBABBBBBAAA BBBBAABBBABAAAAABBBBAAAAABBBBBAABBBBBBBBBAABBAAAAAAAAABBBAAAAABAAABBBBBAAAAABBBBBBAAAAAAABBBBBBBAAAAAAAAAAAAA AAAAABBAAAAAAAABBBBAAAAAAAAABBBBBBBBBAAABBAAAAAAAAAAAABBAAAAAAABBBBBBBBAAABBABBABAAAAAAABBBBBBBAAAAAAAAAAABBA BBBBBBBBBBABBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBABBBBAABBBBABBBAAAABBBAAABBBBBBBBBBBBBBBBAAABBBBBBBBAABBBABBB AABBBAAAAAAABBABBAAAAABBBBBBBBBBAAAAABAAAAAAAAAAABAAABBAAAAAABBBBBBBAAAABAAAAAAAAAABBBAABBBBBAAAABAAAABBBBBAB BABBAAAABBBAAAAAAAAAAABBBBBABBBBABBBBAAABBBBBAAAABBBBBAAAAAAAABBBBBBBBBBABBBAAABBBBBBAAAAAAAAABAAAAABBBBAAAAB BBBBBAAAABAAABBBABABBBBBBAAAAAAABBBBBBBBBBAAAAAAABBBBBBBBBBBBAABBBBBABAAAAABBBBBBBBBBBBBBBBBBBBAAABBBBAAAAAAA AABBBBBBAAAAAAAAABBAAAAAAAABBBAAAAAABBBAABBBBBBBBBBBBBBBBBBBBBAAAABBAAAABBBBBAABAAAAABBABBBAABBAAAABAABABBAAA AAAAAAABBBBBBBBAABBAAAABBBAAABBAAABBBBBBBBABBBBAAAAAAAAAABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Ticks: total 297750, idle 195607, system 70030, user 32113
Kết luận: Console đã xuất ra các chữ A và B xen kẽ, và trước khi kết thúc chương trình, nó hiển thị dòng chữ “Finish Ping-Pong test” trước khi tiến hành dừng Nachos Như vậy, chúng ta đã cài đặt thành công đa chương cho Nachos.
1 Những điều đã làm được
1 Viet thanh cong system call Exec
2 Việt thành công system call Join
3 Viết thành công system call Exit
4 Chạy thử thành công chương trình Scheduler
2 Những điều chưa làm được
Hướng dẫn sử dụng chương trình
- BI: Compile Nachos bằng cach browser dén thu muc /nachos/nachos-3.4/code/, sau đó chạy lệnh: make -_ B2: Vẫn ở vị trí thư mục machos/nachos-3.4/code/, ta chạy lệnh:
/userprog/nachos -rs 1023 —x /test/scheduler -_ B3: Tận hưởng kết quả của chương trình scheduler trên console