Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 19

ĐỒ ÁN HỆ ĐIỀU

HÀNH

HỆ ĐIỀU HÀNH
Quản lý hệ thống tập tin trên Windows

NHÓM THỰC HIỆN


19120148 – Lê Huỳnh Minh Tuấn

19120224 - Lê Thị Thu Hiền

19120151- Nguyễn Trí Tuệ

19120422 - Nguyễn Huy Tùng

19120341 - Phạm Nhựt Quang


ĐỒ ÁN HỆ ĐIỀU
HÀNH

MỤC LỤC
NHÓM THỰC HIỆN..........................................................................................................................1
MỤC LỤC............................................................................................................................................2
BẢNG PHÂN CÔNG CÔNG VIỆC...................................................................................................3
ĐÁNH GIÁ MỨC ĐỘ HOÀN THÀNH.............................................................................................5
ĐỐI VỚI PHÂN VÙNG FAT32.........................................................................................................6
ĐỐI VỚI PHÂN VÙNG NTFS.........................................................................................................11

...................................................................................................................................................................
ĐỒ ÁN HỆ ĐIỀU
HÀNH

BẢNG PHÂN CÔNG CÔNG VIỆC

MSSV Họ và tên Phần thực hiện Đánh giá


mức độ hoàn
thành

19120148 Lê Huỳnh Minh Tuấn Tìm hiểu về NTFS. 100%

Viết chương trình


đọc MFT entry.

Đọc nội dung tập tin


txt

19120224 Lê Thị Thu Hiền Tìm hiểu về NTFS. 100%

Viết chương trình


đọc attribute của
NTFS

Viết báo cáo

19120151 Nguyễn Trí Tuệ Tìm hiểu về FAT32 100%

Viết chương trình


đọc BootSector

Đọc bảng FAT

Đọc cây thư mục ,nội


dung vùng Rdet ,
vùng Data

Vẽ cây thư mục


FAT32

Viết báo cáo phần


FAT32

19120422 Nguyễn Huy Tùng Tìm hiểu về NTFS. 100%

Viết chương trình


đọc sector.
ĐỒ ÁN HỆ ĐIỀU
HÀNH

Vẽ cây thư mục


NTFS

Hỗ trợ fix bug

19120341 Phạm Nhựt Quang Tìm hiểu về NTFS. 100%

Viết chương trình


đọc VBR.

Viết báo cáo


ĐỒ ÁN HỆ ĐIỀU

ĐÁNH GIÁ MỨC ĐỘ HOÀN THÀNH


1. Theo từng yêu cầu:

Yêu cầu Mức độ hoàn thành

Đọc thông tin chi tiết trên phân vùng FAT32 100%

Đọc thông tin chi tiết trên phân vùng NTFS 100%

Đọc cây thư mục trên phân vùng FAT32 100%

Đọc cây thư mực trên phân vùng NTFS 100%

2. Trên cả đồ án:
- Đã hoàn thành tất cả yêu cầu đề đặt ra.
ĐỒ ÁN HỆ ĐIỀU

ĐỐI VỚI PHÂN VÙNG FAT32


1. Mô tả các bước thực hiện
- Bước 1: Nhập thông tin của ổ đĩa cần thực hiện truy vấn (Lưu ý là ổ đĩa nhập
thông qua hàm LPCWSTR drive = L"\\\\.\\D:"). Dựa vào ReadSector đã được
cung cấp sẵn viết hàm ReadBytes để đọc các giá trị tại byte thứ n.
- Bước 2: Để chuyển các byte từ Hex thành Dec, sử dụng hàm Dec.
- Bước 3: Đọc Bootsector (sector 0) theo đúng nội dung lý thuyết bài học.
- Bước 4: Trích xuất các nội dung cần thiết. Lấy được thông tin vùng Rdet và
thông tin vùng Data từ bảng FAT.
- Bước 5: Đọc Sector ở vùng Data.
- Bước 6: Thực hiện đọc các thư mục có ở cây thư mục.
- Bước 7: Đọc file vẽ cây thư mục và xuất nội dung txt.
2. Thư viện đã sử dụng
- #include <windows.h>
- #include <iostream>
- #include <sstream>
- #include <iomanip>
- #include <stdio.h>
- #include <string>
- #include <cstring>
3. Hàm đã thực hiện
- int ReadSector(LPCWSTR drive, int readPoint, BYTE sector[512]):
o Nhận tham số là ổ đĩa đọc, chỉ số byte cần đọc, sector lưu trữ.
o Hàm dùng để đọc các dữ liệu trong sector, cụ thể là 512 byte, trả về các
giá trị dưới dạng hexa.
- int HexToDecimal(string hex):
o Chuyển chuỗi hệ thập lục phân về hệ thập phân.
o Hàm dùng để chuyển chuỗi hệ thập lục phân về hệ thập phân mục đích
là để tính toán cho các lưu trữ dạng little edian như kích thước tệp,
cluster bắt đầu,…
- int ReadBytes(string offset, int numByte, BYTE sector[512]):
o Nhận tham số truyền vào là địa chỉ của byte, số lượng byte cần đọc,
sector lưu trữ.
o Hàm dùng để dùng để đọc các địa chỉ byte và trả về giá trị thập phân trả
ra các giá trị như kích thước tập tin, kích thước lưu trữ, số bảng FAT,…
- void Rdet(BYTE sector[512], int rdet, int cluster, LPCWSTR drive):
o Đọc cây thư mục, đọc các byte trong Rdet.
o Chức năng của hàm: xác định tập tin, dùng lại nhiều lần (đệ qui) để tìm
thư mục con.
- string hexa(int n): Đổi các địa chỉ của entry từ kiểu số trang ký tự để dùng hàm.
ĐỒ ÁN HỆ ĐIỀU

- bool kiemTra(BYTE sector[512]): Hàm đảm bảo tính liên tục của các entry,
kiểm tra entry tiếp theo có rỗng hay không.
4. Demo chương trình
- Link demo youtube : https://www.youtube.com/watch?v=fEh3nQ7abU4
- Ổ đĩa (D:) mới được tạo theo kiểu định dạng FAT32 và có các nội dung:

Hình 1 : Thông tin về ổ đĩa D định dạng FAT32


ĐỒ ÁN HỆ ĐIỀU

Hình 2 : Thông tin thư mục gốc


- Đoạn chương trình dùng để đọc Bootsector lấy các thông tin cần thiết như để bài :
ĐỒ ÁN HỆ ĐIỀU

- Chương trình chạy cho ra các thông số như sau :

Hình 3 : Bảng Boot Sector đọc từ ổ đĩa D

Hình 4 : Thông tin đọc được từ Bootsector

- Hiển thị cây thư mục :


ĐỒ ÁN HỆ ĐIỀU

Hình 5: Cây thư mục Hình 6 : Các tệp con của tệp DOAN

Giải thích : Màn hình Console có xuất hiện 1 cặp mở -|> và đóng <|- có nghĩa
là đang mở thư mục con của một tệp đang là thư mục cha, và nội dung của tệp
định dạng txt được xuất ra.

5. Nguồn tham khảo


Slide bài giảng Hệ Điều Hành Thạc Sĩ Lê Viết Long ĐH KHTN – TPHCM
ĐỒ ÁN HỆ ĐIỀU

ĐỐI VỚI PHÂN VÙNG NTFS


1. Mô tả các bước thực hiện

Một số lưu ý:

Trong phần mô tả quy trình thực hiện, chúng ta sẽ đi qua 4 phần:

- Một số câu hỏi: các câu hỏi mà nhóm thực hành báo cáo gặp phải khi bắt đầu
thực hiện đồ án và câu trả lời cho các vấn đề nhóm đã tìm hiểu và trao đổi với
nhau. Đây là cơ sở để có thể cài đặt các hàm.
- Struct: các struct lưu trữ dữ liệu của các thành phần chính của một ổ đĩa. Lưu
ý,struct chỉ chứa các thông tin cần thiết để thực hiện yêu cầu đồ án, không
phải lưu trữ tất cả thông tin.
- Các hàm chính: điểm qua một số hàm chính và công dụng của nó. Lưu ý, các
bước chi tiết hàm sẽ thực hiện sẽ được chú thích trong Source code ở các file
cpp.
- Mô tả quá trình debug: điểm qua từng bước chương trình sẽ chạy khi Debug.

Ngoài ra trong Source code mà nhóm nộp đồ án, trong các file.h sẽ chú thích
mô tả chức năng của các hàm và file.cpp sẽ chú thích cách hàm triển khai.

Một số vấn đề:

1.1. Xác định cây thư mục

Đầu tiên, ta xác định MFT entry là tệp tin hay thư mục, bằng cách nhìn vào
MFT entry header ở offset 0x16 (2 byte), đây là giá trị cờ báo: 0x01 là tệp tin được
cấp phát, 0x02 là thư mục bị xóa, 0x03 là thư mục được cấp phát, 0x04 và 0x08 là
không xác dịnh. Sau đó, mã ID định danh của một MFT entry là số thứ tự của nó
trong vùng MFT. Ví dụ $MFT có ID là 0, MFT entry tiếp sau nó có mã ID là 1 và
cứ thế tiếp tục. Trong phần nội dung của attribute FILENAME, 8 byte đầu giữ địa
chỉ ID của MFT entry thư mục cha.

Vậy để tạo cây thư mục, MFT entry cần giữ: trạng thái là tệp tin hay thư mục,
mã ID, mã ID của thư mục cha.

Ngoài ra, có hình ảnh dưới đây:


ĐỒ ÁN HỆ ĐIỀU

17 MFT entry đầu của một ổ đĩa luôn xác định, thư mục gốc sẽ luôn mang ID là 5.
Từ MFT entry 18 trở đi sẽ là của tệp tin và các thư mục khác.

1.2. Xác định kết thúc MFT.

Atrribute BITMAP chỉ có ở MFT entry đầu tiên là $MFT, ở đây lưu trữ dữ
liệu một dãy nhị phân cho biết MFT entry nào đang được sử dụng theo thứ tự
ngược lại. VD: 1010 thì MFT entry ở vị trí 1 và 3 được sử dụng. Dựa vào tiền đề
này, ta lấy chỉ số MFT entry lớn nhất được sử dụng, đó là chỉ số của bit 1 cuối
cùng của dãy nhị phân trên. Và khi đọc MFT, ta chạy vòng lặp từ 0 đến chỉ số đó
để đọc các MFT entry.

Trên thực tế, Atrribute BITMAP chỉ lưu trữ địa chỉ dãy nhị phân trên, nội
dung nằm ở vùng Non-resident. Ta phải đọc được vị trí đó bằng một chỉ số đặc
biệt gọi là DataRun. (Thường ở vị trí offset 40h bắt đầu từ đầu Attribute, số lượng
bytes đọc tùy theo chỉ số DataRun quy định).

VD: Chỉ số DataRun

31 01 1 0 1 0 0 0 0 0 0 0
Byte đầu 31 sẽ thể hiện tổng số byte phải đọc, số cluster mà vùng dữ liệu đó
chiếm và cluster bắt đầu.
ĐỒ ÁN HỆ ĐIỀU

Byte thấp (1): cho chúng ta biết cần phải đọc 1 byte sau byte đầu để lấy Số
cluster cần phải đọc. Ở đây là 01h byte, tức là vùng dữ liệu non-resident cần đọc
chiếm 1 cluster.
Byte cao (3): cho chúng ta biết cần phải đọc 3 byte sau byte đầu với số byte
mà byte thấp yêu cầu đọc, trường hợp này, ta bỏ qua 2 byte (1 byte đầu + 1 byte).
Ở đây là 010041h, tức vùng dữ liệu non-resident bắt đầu từ Cluster thứ 65601, từ
đó ta đổi sang sector.
Vậy tổng cộng chúng ta đọc 5 byte (1 + 1 + 3) ở offset 40h. Các byte 00 phía
sau chứng tỏ đã hết DataRun để đọc.
1.3. Đọc data non-resident

Nếu nội dung của tệp tin lớn, cụ thể vượt quá 700 byte thì Atrribute Data sẽ
không giữ nội dung tệp tin mà sẽ lưu trữ địa chỉ nội dung sẽ được lưu ở cluster
nào, chiếm bao nhiêu cluster ở vùng Non-resident. Và dấu hiệu kết thúc nội dung
là 0xFFFF. Ta phải đọc được vị trí đó bằng một chỉ số đặc biệt gọi là DataRun.

Cách đọc DataRun như ở câu 2.

2. Thư viện đã sử dụng


- #include <windows.h>
- #include <iostream>
- #include <sstream>
- #include <iomanip>
- #include <stdio.h>
- #include <vector>
- #include <conio.h>
3. Struct đã thực hiện

//Struct giữ các chỉ số quan trọng của Bios Parameter Block (BPB)
struct BPB
{
int bytePerSector; //Số byte cho 1 sector
int sectorPerCluster; //Số sector cho 1 cluster
int sectorPerTrack; //Số sector cho 1 track
int numHead; //Số head
int64 numSectorOfDisk; //Số sector của ổ đĩa
};

//Struct giữ vị trí bắt đầu và kết thúc của vùng Master File Table (MFT)
struct MFT
{
int startClusterMFT; //Cluster bắt đầu MFT
ĐỒ ÁN HỆ ĐIỀU

double bytePerMFTEntry; //Số byte cho 1 MFT Entry


int lastMFTEntry; //MFT Entry cuối cùng
};

//Struct lưu giữ dữ liệu ở Attribute Data của một MFT entry
struct AttributeData
{
string content;
};

//Struct giữ tên ở Attribute FILENAME của một MFT entr


struct AttributeFileName
{
string filename;
int parentFolderIndex; //địa chỉ thư mục cha (MFT entry)
};

// Attribute Bitmap lưu trữ chuỗi mã nhị phân cho biết entry nào được sử dụng,
chỉ có ở $MFT
struct AttributeBitmap
{
int magicNumber;
};

//Struct giữ các thông tin cơ bản của Atrribute.


//Nếu type (loại Attribute) nào thì Atrribute đó sẽ giữ dữ liệu, còn lại trống.
struct Attribute
{
int type; //loại Attribute
int startIndex; //vị trí bắt đầu Attribute
int size; //kích thước Attribute
int startContentIndex; //vị trí bắt đầu phần nội dung Attribute
int contentSize; //kích thước phần nội dung Attribute
AttributeBitmap Bitmap;// type = 176
AttributeData Data;// type = 128
AttributeFileName FileName;// type = 48
};

//Struct giữ các thông tin cơ bản của MFT entry


struct MFTEntry
ĐỒ ÁN HỆ ĐIỀU

{
int id;//ID của MFT entry
int64 idSector; //sector bắt đầu MFT entry
int type; //0: tập tin đã xóa, 1: tập tin được cấp phát, 2: thư mục đã xóa,
3: thư mục được cấp phát
BYTE sector1[512]; //nửa entry đầu
BYTE sector2[512]; //nửa entry cuối
vector<Attribute> attributes; //danh sách các Attribute
vector< int64> sectors; //các sector mà data được lưu trữ
};

//Struct tệp tin, các thông tin cơ bản được lấy từ các attribute của mft entry
tương ứng
struct File
{
int id;
string name;
int size;//Kích thước
string data;
int parentIndex;//ID cha
vector< int64> sectors; //các sector lưu trữ
};

//Struct thư mục, các thông tin cơ bản được lấy từ các attribute của mft entry
tương ứng
struct Folder
{
int id;
string name;
vector<File> child;//tệp tin con
vector<Folder> folderchild;//thư mục con
int parentIndex;
vector< int64> sectors; //các sector lưu trữ
};
4. Hàm đã thực hiện

4.1. Các hàm phụ trợ để đọc dãy mã nhị phân

Đây là các hàm phụ để giúp đọc các chỉ số của các struct. Ở đây, chia làm hai
phần là ReadSector và ReadByte.
ĐỒ ÁN HỆ ĐIỀU

Cụ thể chức năng từng hàm đã được chú thích trong Source code ở
ReadSector.h và ReadByte.h

4.2. Bios Parameter Block (BPB)


Hàm đọc các thông tin vào struct BPB ở sector 0

void ReadBPB(BPB& bpb, BYTE sector[512])


4.3. Master File Table (MFT)

a. MFT

Hàm đọc các thông tin vào struct MFT ở sector 0

void ReadMFT(MFT& mft, BPB bpb, BYTE sector[512], LPCWSTR drive)

Trong đó, để xác định chỉ số MFT cuối cùng (đã đề cập ở câu hỏi 3, phần Mở
đầu) ta gọi hàm int GetLastMFTEntry(MFTEntry entry).

Hàm sẽ lấy chỉ số magicNumber từ struct AttributeBitmap của $MFT(hàm đọc


MFT entry và Atrribute sẽ được nhắc đến phần b, c).
Hàm này chỉ được gọi một lần trong Source Code, vì chỉ có $MFT có
AttributeBitmap.
b. MFT entry
Hàm đọc các thông tin vào struct MFT entry ở sector, trong đó quan trọng nhất
là vector Atrribute giữ các phần tử .

bool ReadMFTEntry(MFTEntry& entry, int startSectorMFT, LPCWSTR drive)

c. Atrribute
- Hàm đọc các danh sách các attribute của MFT entry, ở đây ta chú ý đến 3
atrribute FILENAME, DATA, BITMAP (Chỉ có ở $MFT)
vector<Attribute> ReadAttributes(MFTEntry mftentry, int startAttr,
LPCWSTR drive)

Hàm sẽ thực hiện một vòng lặp, mỗi lần lặp đọc 1 atrribute đến khi hết.
Ở đây, chúng ta sẽ bàn về điều kiện hủy vòng lặp
while (startAttr + attribute.size < 1024)
{



startAttr += attribute.size; //Điểm bắt đầu của attribute tiếp theo bằng
tổng điểm bắt đầu và chiều dài của attribute hiện tại
ĐỒ ÁN HỆ ĐIỀU

attribute.size = ReadAttributeBytes(startAttr + 4, 4, entry);//Cập nhật chiều


dài attribute tiếp theo
attributes.push_back(attribute);//Thêm attribute vào vector
}
Điều kiện dừng là tổng của điểm bắt đầu và chiều dài của attribute sắp xét nhỏ
hơn 1024 (startAttr + attribute.size < 1024), điểm kết thúc của MFT entry đánh
dấu bằng 0xFF, nếu hàm đọc được giá trị này thì attribute.size rất lớn thỏa điều
kiện dừng.
4.4. Cây thư mục
Các hàm phục vụ cho việc đọc cây thư mục được khai báo ở File.h
Đây là hàm đọc các MFT entry vào các tệp tin, thư mục và xếp cây thư mục,
cuối hàm, xuất cây thư mục ra màn hình.
void PrintRootFolder(vector<MFTEntry> entries, vector<File>& files,
vector<Folder>& folders);
4.5. Thứ tự thực thi

- Gọi hàm void ReadNTFS(LPCWSTR drive, BYTE sector[512]) để bắt


đầu đọc.
- Gọi hàm ReadBPB(bpb, sector) để đọc BPB ở sector đầu tiên.

- Gọi hàm ReadMFT(mft, bpb, sector, drive); Trong đó, để lấy chỉ số MFT entry
cuối cùng thì gọi hàm int GetLastMFTEntry(MFTEntry entry) ở magicNumber
struct AttributeBitmap.
- Lặp vòng lặp từ MFT entry đầu tiên đến chỉ số MFT cuối cùng để gọi hàm
ReadMFTEntry(entry, mft.startClusterMFT * bpb.sectorPerCluster, i, drive);
- Mỗi MFT entry sẽ đọc header để biết tệp tin hay thư mục và đọc vị trí của
atrribute đầu tiên. Sau đó đọc lần lượt các attribute của mình vào
vector<Attribute>. Nếu là FILENAME thì sẽ lưu tên của tệp tin/thư mục và
mã ID của cha; DATA thì đọc nội dung, tùy theo resident hay non-resident mà
đọc ở vùng MFT hay vùng Non-resdident; BITMAP chỉ có ở $MFT và nội
dung được lưu ở vùng Non-resident.
- Sau đó, thực hiện hàm PrintRootFolder(entries, files, folders) để đọc các MFT
entry vào tệp tin, thư mục và in ra cây thư mục.
ĐỒ ÁN HỆ ĐIỀU

- Ta thấy được ở thư mục gốc có thư mục A, tệp tin New Text Document.txt,
DataGeneration1.sql.

- Sau đó người dùng có thể chọn truy xuất tiếp tệp tin hay thư mục bằng
cách chọn 0 hay 1.
ĐỒ ÁN HỆ ĐIỀU

- Người dùng tiếp tục nhập ID tệp tin hay thư mục để hiển thị nội dung bên
trong.
- Kết thúc khi nhấn ESC.
5. Demo chương trình
Link youtube: https://youtu.be/1_u2YS6PdZM
6. Tài liệu tham khảo
- Slide bài giảng Hệ Điều Hành Thạc Sĩ Lê Viết Long ĐH KHTN – TPHCM
- https://sabercomlogica.com/en/ntfs-non-resident-and-no-named-attributes/
- Chuỗi bài blog Hệ thống tệp tin NTFS của thầy Lê Gia Công:
https://legiacong.blogspot.com/2014/04/he-thong-quan-ly-tap-tin-ntfs-4-vbr-
bpb.html

You might also like