





Preview text:
Báo cáo nghiên cứu về luồng trong Windows Mục lục 1. Giới thiệu 2. Luồng là gì? 3. Các loại luồng 4. Cách tạo luồng 5. Cách điều khiển luồng 6. Cách kết thúc luồng 7.
Ưu điểm và nhược điểm của luồng, lợi ích của lập trình đa luồng 8. Kết luận 1. Giới thiệu
Luồng là một khái niệm quan trọng trong hệ điều hành Windows, cho phép
thực thi song song các tác vụ độc lập. Luồng có thể được sử dụng để cải
thiện hiệu suất của các ứng dụng, bằng cách cho phép chúng thực hiện
nhiều tác vụ cùng một lúc. 2. Luồng là gì?
Luồng là một đơn vị thực thi cơ bản trong hệ điều hành Windows. Mỗi
luồng có một bộ thanh ghi riêng(Registers), bộ nhớ cục bộ(không gian
stack) và hàng đợi ngắt riêng. Luồng có thể chia sẻ bộ nhớ với các luồng
khác, nhưng chúng có bộ thanh ghi và hàng đợi ngắt riêng biệt.
Luồng được tạo bằng cách gọi hàm CreateThread(). Hàm này trả về một
con trỏ đến luồng mới được tạo. 3. Các loại luồng
Có hai loại luồng trong Windows:
• Luồng user mode: Luồng user mode được thực thi trong không gian người
dùng. Các luồng user mode có thể truy cập các tài nguyên người dùng,
chẳng hạn như cửa sổ, màn hình và bàn phím. Luồng user mode được quản
lý bởi bộ xử lý (CPU) và không cần sự tham gia của kernel (hệ điều hành)
Luồng user mode có các ưu điểm sau: •
Dễ dàng sử dụng và quản lý. •
Không cần sử dụng các API hệ thống phức tạp. • Tốc độ thực thi cao.
Luồng user mode có các nhược điểm sau: •
Chỉ có thể truy cập vào các tài nguyên trong không gian người dùng. •
Không thể truy cập trực tiếp vào phần cứng. •
Có thể gây ra các vấn đề về đồng bộ dữ liệu, nếu không được sử dụng đúng cách.
• Luồng kernel mode: Luồng kernel mode được thực thi trong không gian
nhân. Các luồng kernel mode có quyền truy cập vào các tài nguyên hệ
thống, chẳng hạn như phần cứng và bộ nhớ.
Luồng kernel mode có các ưu điểm sau: •
Có thể truy cập trực tiếp vào phần cứng. •
Có thể truy cập vào tất cả các tài nguyên của hệ thống. •
Ít gây ra các vấn đề về đồng bộ dữ liệu.
Luồng kernel mode có các nhược điểm sau: •
Khó sử dụng và quản lý. •
Cần sử dụng các API hệ thống phức tạp. •
Tốc độ thực thi thấp hơn luồng user mode. 4. Cách tạo luồng
Luồng được tạo bằng cách gọi hàm CreateThread(). Hàm này trả về một
con trỏ đến luồng mới được tạo. C++
// Tạo một luồng user mode
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
// Tạo một luồng kernel mode
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
Hàm CreateThread() có các tham số sau: •
lpThreadAttributes: Con trỏ đến một cấu trúc SECURITY_ATTRIBUTES. Nếu tham số này
là NULL, thì luồng mới sẽ được tạo mà không có bất kỳ quyền bảo mật nào. •
dwStackSize: Kích thước ngăn xếp của luồng mới. Nếu tham số này là 0, thì
Windows sẽ sử dụng kích thước ngăn xếp mặc định. •
lpStartAddress: Địa chỉ của hàm sẽ được thực thi trong luồng mới. •
lpParameter: Con trỏ đến tham số được truyền cho hàm được chỉ định bởi tham số lpStartAddress. •
dwCreationFlags: Các cờ chỉ định cách luồng mới được tạo. lpThreadId: Con trỏ
đến một biến sẽ chứa ID của luồng mới.
+ Tham số lpThreadAttributes là một con trỏ đến một cấu trúc
SECURITY_ATTRIBUTES. Cấu trúc này xác định quyền bảo mật của luồng mới.
Nếu tham số lpThreadAttributes là NULL, thì luồng mới sẽ được tạo mà không có
bất kỳ quyền bảo mật nào.
Nếu tham số lpThreadAttributes không phải là NULL, thì bạn cần chỉ định các giá trị
cho các thành phần sau của cấu trúc:
- nLength: Chiều dài của cấu trúc.
- lpSecurityDescriptor: Con trỏ đến một cấu trúc SECURITY_DESCRIPTOR. Cấu trúc này
xác định quyền bảo mật của luồng mới.
+ Tham số dwStackSize là kích thước ngăn xếp của luồng mới. Nếu tham số này là
0, thì Windows sẽ sử dụng kích thước ngăn xếp mặc định.
Kích thước ngăn xếp là lượng bộ nhớ được cấp phát cho luồng mới để lưu trữ dữ
liệu cục bộ. Kích thước ngăn xếp tối thiểu là 1 MB.
+ Tham số lpStartAddress là địa chỉ của hàm sẽ được thực thi trong luồng mới.
Hàm này phải có kiểu trả về void và không có đối số.
+ Tham số lpParameter là con trỏ đến tham số được truyền cho hàm được chỉ định
bởi tham số lpStartAddress.
Thao tác này cho phép bạn truyền dữ liệu đến luồng mới.
+Tham số dwCreationFlags là một số nguyên chỉ định cách luồng mới được tạo.
+Tham số lpThreadId là con trỏ đến một biến sẽ chứa ID của luồng mới.
ID của luồng là một số nguyên duy nhất xác định luồng.
5. Cách điều khiển luồng
Luồng có thể được điều khiển bằng cách sử dụng các hàm sau:
• SuspendThread(): Tạm dừng luồng. Hàm này sẽ đặt trạng thái của luồng thành WAIT.
• ResumeThread(): Tiếp tục luồng. Hàm này sẽ đặt trạng thái của luồng thành RUN.
• TerminateThread(): Hàm này sẽ gửi một tín hiệu kết thúc đến luồng. #include
void ThreadProc(void* lpParameter) {
// Thực hiện tác vụ của luồng printf("Hello, world!!\n"); } int main() { // Tạo một luồng mới
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); // Tạm dừng luồng SuspendThread(hThread); // Tiếp tục luồng ResumeThread(hThread);
// Đợi luồng kết thúc
WaitForSingleObject(hThread, INFINITE); return 0; } 6. Cách kết thúc luồng
Luồng kết thúc khi nó hoàn thành tác vụ của mình hoặc khi nó bị hủy.
Luồng cũng có thể kết thúc do lỗi hoặc do hệ điều hành. #include
void ThreadProc(void* lpParameter) {
// Thực hiện tác vụ của luồng printf("Hello, world!!\n"); } int main() { // Tạo một luồng mới
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); // Kết thúc luồng TerminateThread(hThread, 0); return 0; }
7. Ưu điểm và nhược điểm của luồng •
Tăng hiệu năng: Luồng cho phép xử lý các tác vụ song song, giúp tăng hiệu năng của chương trình. •
Tăng khả năng sử dụng: Luồng cho phép chia nhỏ các tác vụ thành các phần nhỏ
hơn, giúp dễ dàng quản lý và bảo trì. •
Tăng tính linh hoạt: Luồng cho phép thực hiện nhiều tác vụ cùng một lúc, giúp ứng
dụng trở nên linh hoạt hơn.
Nhược điểm của luồng: •
Tăng độ phức tạp: Luồng có thể làm tăng độ phức tạp của chương trình, vì cần phải
xử lý các vấn đề như đồng bộ dữ liệu và quản lý tài nguyên. •
Tăng khả năng xảy ra lỗi: Luồng có thể làm tăng khả năng xảy ra lỗi, nếu không
được sử dụng đúng cách. 8. Kết luận
Luồng là một khái niệm quan trọng trong hệ điều hành Windows, cho phép
thực thi song song các tác vụ độc lập. Luồng có thể được sử dụng để cải
thiện hiệu suất của các ứng dụng, bằng cách cho phép chúng thực hiện
nhiều tác vụ cùng một lúc.
Để sử dụng luồng hiệu quả, có một số vấn đề cần lưu ý sau:
• Xung đột tài nguyên: Các luồng có thể truy cập cùng một tài nguyên,
chẳng hạn như bộ nhớ hoặc file. Điều này có thể dẫn đến xung đột tài
nguyên, nếu các luồng không được đồng bộ hóa đúng cách.
• Concurrency: Các luồng có thể chạy song song, điều này có thể dẫn
đến các vấn đề về concurrency, chẳng hạn như race condition và deadlock.
• Performance: Sử dụng luồng có thể cải thiện hiệu suất của ứng dụng,
nhưng cũng có thể làm giảm hiệu suất nếu không được sử dụng đúng cách.