Bài giảng Nguyên lí hệ điều hành - Chương 4: Luồng (Threads)
Bạn đang xem tài liệu "Bài giảng Nguyên lí hệ điều hành - Chương 4: Luồng (Threads)", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Tài liệu đính kèm:
- bai_giang_nguyen_li_he_dieu_hanh_chuong_4_luong_threads.pdf
Nội dung text: Bài giảng Nguyên lí hệ điều hành - Chương 4: Luồng (Threads)
- Nội dung chương 4 BÀI GIẢNG NGUYÊN LÝ HỆ ĐIỀU HÀNH Giới thiệu chung Các mô hình đa luồng Các vấn đề về luồng Chương 4: Luồng (Threads) Một số loại luồng Phạm Quang Dũng Bộ môn Khoa học máy tính Khoa Công nghệ thông tin Trường Đại học Nông nghiệp Hà Nội Website: fita.hua.edu.vn/pqdung Bài giảng Nguyên lý Hệ điều hành 4.2 Phạm Quang Dũng ©2008 4.1. Giới thiệu chung Các tiến trình đơn luồng và đa luồng Luồng là một đơn vị cơ bản của sự sử dụng CPU Là một dòng điều khiển trong một tiến trình. Nếu tiến trình có nhiều luồng, nó có thể thực hiện nhiều tác vụ tại một thời điểm. Luồng bao gồm: z Mã luồng (thread ID) z Bộ đếm chương trình (PC) z Tập thanh ghi (register set) z stack Các luồng trong một tiến trình chia sẻ với nhau đoạn mã (code), đoạn dữ liệu (data) và các tài nguyên hệ thống khác như các tệp mở, các tín hiệu. Bài giảng Nguyên lý Hệ điều hành 4.3 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.4 Phạm Quang Dũng ©2008 1
- Sự thúc đẩy Lợi ích của tiến trình đa luồng Tạo tiến trình là một công việc "nặng nhọc" Đáp ứng nhanh: cho phép chương trình tiếp tục thực hiện thậm chí khi một bộ phận của nó bị khóa hoặc đang thực Nhiều phần mềm chạy trên các PC hiện nay là đa luồng hiện một hoạt động dài. (multithreaded). Một ứng dụng thường được thực hiện như một tiến trình riêng với một vài luồng điều khiển. Chia sẻ tài nguyên: lợi ích của chia sẻ code là cho phép một ứng dụng có một số luồng khác nhau hoạt động trong Vd1: Trình soạn thảo văn bản cùng một không gian địa chỉ. z 1 luồng hiển thịảnh, chữ Kinh tế: tạo và chuyển ngữ cảnh luồng kinh tế hơn so với z 1 luồng đọc phím nhấn bởi người sử dụng tiến trình. Trong HĐH Solaris 2, tạo tiến trình chậm hơn 30 z 1 luồng thực hiện việc kiểm tra chính tả và ngữ pháp lần, chuyển ngữ cảnh tiến trình chậm hơn 5 lần với luồng. Vd2: web-server tạo 1 luồng nghe các yêu cầu từ client. Thực hiện trong kiến trúc multiprocessor: lợi ích của đa Khi có yêu cầu, thay vì tạo 1 tiến trình khác, nó sẽ tạo một luồng tăng lên trong kiến trúc multiprocessor, vì các luồng luồng khác để phục vụ yêu cầu. có thể chạy song song trên các processor. Bài giảng Nguyên lý Hệ điều hành 4.5 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.6 Phạm Quang Dũng ©2008 User Threads Kernel Threads Được hỗ trợ trên kernel và được thực hiện bởi một thư Được hỗ trợ trực tiếp bởi HĐH. viện luồng tại mức người sử dụng (user level). Kernel thực hiện tạo luồng, lập lịch và quản lý trong không Tất cả sự tạo luồng và lập lịch được thực hiện trong không gian kernel. Do đó, tạo và quản lý các kernel thread nói gian người sử dụng. Do đó, các user-level thread nói chung chung chậm hơn các user thread. nhanh để tạo và quản lý. Nếu một luồng thực hiện một system call khóa, kernel có Tuy nhiên, chúng cũng có hạn chế: khi kernel là đơn luồng, thể lập lịch một luồng khác để thực hiện. Trong môi trường nếu có 1 user-level thread thực hiện một system call khóa, multiprocessor, kernel có thể lập lịch các luồng trên các nó sẽ gây cho toàn bộ tiến trình bị khóa, mặc dù các tiến processor khác nhau. trình khác vẫn có thể chạy trong ứng dụng. Vd: Các HĐH hiện nay: Windows NT/2000/XP, Solaris, Vd: POSIX Pthreads, Win32 threads, Java threads Tru64 UNIX, LINUX, Mac OS X. Bài giảng Nguyên lý Hệ điều hành 4.7 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.8 Phạm Quang Dũng ©2008 2
- 4.2. Các mô hình đa luồng Mô hình Many-to-One Để chạy trên CPU, các user thread cuối cùng cũng phải Nhiều user-level thread được ánh xạ vào một kernel thread. được ánh xạ vào 1 Nhiều HĐH hỗ trợ cả user thread và kernel thread, thể kernel thread hiện trong các mô hình đa luồng phổ biến: z Many-to-One z One-to-One z Many-to-Many Quản lý luồng được thực hiện trong không gian người sử dụng → nhanh nhưng tiến trình dễ bị khóa. z 2-level Các luồng không thể chạy song song trong các hệ thống multiprocessor. Vd: Solaris Green Theads, GNU Portable Threads Bài giảng Nguyên lý Hệ điều hành 4.9 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.10 Phạm Quang Dũng ©2008 Mô hình One-to-One Mô hình Many-to-Many Mỗi user-level thread được ánh xạ vào 1 kernel thread Nhiều user-level thread (n) được ánh xạ vào nhiều kernel thread (m) m ≤ n Cho phép tiến trình khác chạy khi có 1 tiến trình tạo system call khóa. Người phát triển có thể tạo bao nhiêu user thread tùy ý, các kernel thread tương ứng có thể chạy song song trên Cho phép nhiều luồng chạy song song trên multiprocessor. multiprocessor. Khi 1 thread thực hiện 1 system call khóa, Cần giới hạn số luồng được hỗ trợ bởi HĐH kernel có thể lập lịch 1 thread khác để thực hiện. Vd: Windows NT/2000/XP, Linux, Solaris 9 trở đi Vd: Solaris trước phiên bản 9, Windows 2000/NT với gói ThreadFiber Bài giảng Nguyên lý Hệ điều hành 4.11 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.12 Phạm Quang Dũng ©2008 3
- Mô hình 2 mức 4.3. Các vấn đề về luồng Các system call fork() và exec() Tương tự như Many-to-many, chỉ khác là nó cho phép 1 user thread được giới hạn bởi 1 kernel thread Hủy luồng Ví dụ Xử lý tín hiệu z IRIX Thread pools z HP-UX Dữ liệu riêng cho luồng z Tru64 UNIX Giao tiếp giữa kernel và thư viện luồng z Solaris 8 trở về trước Bài giảng Nguyên lý Hệ điều hành 4.13 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.14 Phạm Quang Dũng ©2008 4.3.1. Các system call fork và exec (trong UNIX) 4.3.2. Hủy bỏ luồng Là tác vụ thực hiện hủy bỏ 1 thread trước khi nó kết thúc. Nếu một luồng trong chương trình gọi fork(), một số HĐH UNIX có 2 phiên bản của fork Vd: nếu nhiều luồng cùng đang tìm kiếm trong CSDL, nếu 1 luồng tìm thấy, các luồng còn lại nên được dừng lại. z Một sao lại tất cả các thread Sự hủy luồng có thể diễn ra theo 2 cách: z Một chỉ sao lại thread đã gọi fork z Hủy không đồng bộ: lập tức ngừng luồng Nếu 1 luồng gọi exec, chương trình được xác định trong tham số của exec sẽ thay thế toàn bộ tiến trình (gồm tất z Hủy trì hoãn: luồng bị hủy có thể kiểm tra tiên đoán xem nó cả các luồng). có nên bị hủy không, cho phép nó có một cơ hội tự hủy theo cách có trật tự. Bài giảng Nguyên lý Hệ điều hành 4.15 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.16 Phạm Quang Dũng ©2008 4
- 4.3.3. Xử lý tín hiệu 4.3.4. Thread Pools Tư tưởng chung đằng sau một thread pool là tạo nhiều Các tín hiệu được sử dụng trong HĐH UNIX để báo cho tiến luồng tại lúc bắt đầu tiến trình và đặt chúng vào một pool - trình biết có một sự kiện đặc biệt đã xuất hiện. nơi chúng "ngồi" và đợi việc. Các tín hiệu được xử lý bởi 1 trình xử lý theo các bước: Khi server nhận một yêu cầu, nó "đánh thức" một luồng 1. Tín hiệu được sinh ra bởi một sự kiện đặc biệt trong pool - nếu nó sẵn sàng - truyền cho nó yêu cầu để 2. Tín hiệu được đưa đến 1 tiến trình phục vụ. Khi hoàn thành, luồng lại trở về pool chờ công 3. Sau đó, tín hiệu được xử lý. việc khác. Lợi ích: Các lựa chọn: z Dùng luồng đã tồn tại phục vụ nhanh hơn so với chờ đợi để z Đưa tín hiệu tới luồng tương ứng dành cho tín hiệu tạo luồng. z Đưa tín hiệu tới tất cả luồng trong tiến trình z thread pool giới hạn số luồng tồn tại ở một thời điểm. Điều z Đưa tín hiệu tới một số luồng trong tiến trình này đặc biệt quan trọng trên các hệ thống không thể hỗ trợ z Ấn định một luồng chuyên nhận tất cả các tín hiệu cho tiến trình số lượng lớn các luồng cùng lúc. Bài giảng Nguyên lý Hệ điều hành 4.17 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.18 Phạm Quang Dũng ©2008 4.3.5. Dữ liệu riêng của luồng 4.3.6. Giao tiếp kernel - thư viện luồng Các luồng thuộc 1 tiến trình có thể chia sẻ tài nguyên Cả mô hình many-to-many và mô hình 2-mức đều yêu của tiến trình. cầu sự giao tiếp để duy trì số lượng thích hợp các kernel Nhưng một số trường hợp: mỗi luồng cần dữ liệu riêng thread phân phối cho ứng dụng. Ví dụ: trong một hệ thống xử lý giao dịch, ta nên phục upcall –cơ chế giao tiếp giữa kernel và thư viện luồng: vụ mỗi giao dịch trong 1 luồng riêng. Hơn nữa mỗi giao z Kernel cung cấp một ứng dụng gồm một tập các BXL ảo dịch có thể được gán 1 id duy nhất ⇒ sử dụng dữ liệu z ứng dụng có thể lập lịch các user thread vào một BXL ảo riêng cho luồng. khả dụng. Lợi ích: z Kernel phải thông báo cho ứng dụng về các sự kiện nào đó z Cho phép mỗi luồng có bản copy dữ liệu riêng của nó. Sự giao tiếp này cho phép một ứng dụng duy trì số z Hữu ích khi bạn không có kiểm soát tiến trình tạo luồng lượng kernel thread đúng đắn. (nghĩa là khi sử dụng 1 thread pool). Bài giảng Nguyên lý Hệ điều hành 4.19 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.20 Phạm Quang Dũng ©2008 5
- 4.4. Một số loại luồng 4.4.2. Luồng Windows XP 4.4.1. Pthreads Áp dụng cho "họ" Windows: 95/98/2000/XP/NT (Win32 API) Một ứng dụng Windows chạy như một tiến trình riêng, mỗi tiến trình có Là chuẩn POSIX (IEEE 1003.1c), định ra một API cho thể chứa một hoặc nhiều luồng. việc tạo và đồng bộ hóa luồng. Sử dụng mô hình ánh xạ one-to-one API xác định hành vi (behavior) của thư viện luồng, sự Cũng hỗ trợ thư viện fiber, cung cấp chức năng của mô hình many-to- thực thi (implementation) phụ thuộc vào sự phát triển many. của thư viện. Bằng cách sử dụng thư viện luồng, mọi luồng của tiến trình có thể truy nhập không gian địa chỉ của tiến trình. Phổ biến trong các HĐH dạng UNIX (Solaris, Linux, Các thành phần của luồng: Mac OS X, True64 UNIX) z một thread ID z tập thanh ghi biểu diễn trạng thái của processor context z một user stack và một kernel stack của luồng z một vùng lưu trữ riêng. Bài giảng Nguyên lý Hệ điều hành 4.21 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.22 Phạm Quang Dũng ©2008 4.4.3. Luồng LINUX 4.4.4. Luồng Java Ngoài fork(), Linux cũng cung cấp system call tương tự Java là một trong số ít các NNLT có cung cấp sự hỗ là clone() để tạo luồng, nhưng thay vì tạo 1 bản copy trợ tạo và quản lý luồng tại mức ngôn ngữ: có các của tiến trình gọi, nó tạo 1 tiến trình mới (tiến trình con). lệnh tạo và thao tác với các luồng điều khiển trong chương trình. Tiến trình mới trỏ vào cấu trúc dữ liệu của tiến trình cha, do đó cho phép tiến trình con chia sẻ bộ nhớ và các tài Các luồng được quản lý bởi JVM (Java Virtual nguyên khác của cha. Machine), không phải bởi thư viện luồng hay bởi kernel. Điều thú vị là Linux không phân biệt giữa tiến trình và luồng. Thực tế, Linux thường dùng thuật ngữ task để chỉ Tất cả các chương trình Java chứa ít nhất 1 luồng một dòng điều khiển trong chương trình. điều khiển đơn (khi chương trình chỉ có 1 phương thức main). Bài giảng Nguyên lý Hệ điều hành 4.23 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.24 Phạm Quang Dũng ©2008 6
- Các kỹ thuật tạo luồng trong CT Java Vd: Tạo luồng trong Java 1. Tạo một lớp dẫn xuất của lớp Thread và chồng class Worker1 extends Thread { public void run() { phương thức . run() System.out.println("I Am a Worker Thread"); z Một đối tượng của lớp dẫn xuất sẽ chạy như 1 luồng } } điều khiển riêng trong JVM. Phương thức start sẽ thực sự tạo luồng mới. public class ThreadTester { public static void main(String args[]) { 2. Định nghĩa một lớp thực thi Runnable interface: Worker1 runner = new Worker1(); public interface Runnable{ runner.start(); public abstract void run(); System.out.println("I Am The Main Thread"); } } } Bài giảng Nguyên lý Hệ điều hành 4.25 Phạm Quang Dũng ©2008 Bài giảng Nguyên lý Hệ điều hành 4.26 Phạm Quang Dũng ©2008 Các trạng thái của luồng Java End of Chapter 4 Bài giảng Nguyên lý Hệ điều hành 4.27 Phạm Quang Dũng ©2008 7