Polling v.s Interrupt Interrupt
CHƯƠ NG NG II: Polling và Interrupt
Một hệ thống thờ i gian thực đượ c gọi là “điều khiển sự kiện” có ngh ĩ a là hệ thống ng đó phải có chức năng chính là phản ứng lại các sự kiện xảy ra trong môi tr ườ ườ ng của hệ thống. Vậy thì hệ thống phản ứng lại các sự kiện như thế nào. Hiện nay có hai phươ ng ng pháp tiế p cận vấn đề này. Phươ ng ng pháp đầu tiên là Polling hay Vòng l ặ p Polling Polling .
Hình 1 – Vòng l ặ p Polling
Hãy xem đoạn code trong hình 1. Ch ươ ng ng trình đượ c bắt đầu bằng một vài cài đặt ban đầu cho hệ thống r ồi truy cậ p vào trong một vòng lặ p vô hạn, trong đó, các sự kiện mà hệ thống có thể phản ứng lại đượ c kiểm tra. Khi có m ột sự kiện xảy ra, dịch vụ phản ứng lại sự kiện đó đượ c kích hoạt. Tiến trình thực hiện của vòng lặ p trên tỏ ra khá đơ n giản và thích hợ p vớ i những hệ thống nhỏ không đòi hỏi quá gắt gao về mặt thờ i gian. Tuy nhiên, cũng có một số vấn đề cần bàn đến: - Thờ i gian phản ứng lại sự kiện phụ thuộc r ất lớ n vào vị trí mà chươ ng ng trình đang thực hiện trong vòng lặ p. Lấy ví dụ: Nếu sự kiện event_1 xảy ra ngay ướ c câu lệnh if(event_1) thì thờ i gian phản ứng là r ất ngắn. Nhưng nếu sự tr ướ kiện event_1 xảy ra ngay sau khi câu l ệnh kiểm tra đó, chươ ng ng trình lúc này phải quét toàn bộ vòng lặ p và quay tr ở ở về điểm đầu và thực hiện dịch vụ của sự kiện event_1. - Và cũng là một hệ quả tất yếu, thờ i gian phản ứng cũng là một hàm của số lượ ng ng sự kiện đượ c kích hoạt tại một thờ i điểm và sau đó là thờ i gian thực hiện các d ịch vụ trong một lần quét vòng lặ p của chươ ng ng trình.
Võ Duy Thành –
[email protected] –
[email protected]
1 / 6
Polling v.s Interrupt
- Tất cả các sự kiện đượ c chươ ng trình đối xử một cách bình đẳng và không có sự ưu tiên nào cả. - Khi có một đặc tính mớ i, do đó là dịch vụ mớ i, đượ c thêm vào chươ ng trình, thờ i gian phản ứng lại dài thêm ra. Phươ ng pháp tiế p cận thứ 2 là ng ắ t ( Interrupt ). R ất hữu dụng và cũng gây không ít khó khăn cho ngườ i lậ p trình. Ý tưở ng của ngắt: sự xuất hiện của một sự kiện có thể “ngắt” tiến trình thực hiện của chươ ng trình, “nhồi” thêm và thực hiện một tiến trình khác vào như hình 2. Khi tiến trình nhồi thêm đượ c thực hiện xong, chươ ng trình chính lại đượ c thực hiện tiế p từ thờ i điểm bị ngắt. Tiến trình của sự kiện ngắt đượ c thực hiện ngay lậ p tức mà không phải quan tâm đến chươ ng trình chính. Những tiến trình như thế ngườ i ta gọi là “chươ ng trình con d ịch vụ ng ắt ” ( Interrupt Service Routine) viết tắt ISR. Các thế hệ vi xử lý hiện nay thườ ng thực hiện 3 loại ngắt khác nhau - Câu lệnh INT, hay nhiều khi còn đượ c nhắc đến vớ i cái tên là TRAP (b ẫy). Nó như một câu lệnh để gọi một chươ ng trình con đặc biệt. Chúng ta sẽ đề cậ p đến nó sau. - Các tr ườ ng hợ p đặc biệt của bộ xử lý. Các điều kiện lỗi như lỗi chia 0, lỗi truy cậ p bất hợ p pháp vào bộ nhớ có thể đượ c điều khiển thông qua cơ chế ngắt.
Hình 2 - Ng ắt
Hai loại ngắt k ể trên đồng bộ vớ i việc thực hiện lệnh. Trong đó, INT chính là một câu lệnh và các l ỗi đặc biệt của bộ xử lý chính là k ết quả tr ực tiế p của việc thực hiện lệnh.
Võ Duy Thành –
[email protected]
2 / 6
Polling v.s Interrupt
Loại ngắt thứ 3 đượ c tạo ra bở i sự kiện xảy ra bên ngoài bộ xử lý. Loại ngắt này đượ c tạo ra bở i các I/O phần cứng và xảy ra không đồng bộ vớ i việc thực hiện lệnh. Các ngắt ngoài không đồng bộ này: - Làm tối đa hoá hiệu suất và thông lượ ng của hệ thống máy tính - Gây ra phần lớ n các lỗi và r ắc r ối cho ngườ i lậ p trình Hầu hết các bộ xử lý đều sử dụng lượ c đồ ngắt giống nhau. Hình 3 ch ỉ ra kiến trúc ngắt của Intel x86. 1kilo byte đầu tiên của bộ nhớ đượ c giành cho bảng véct ơ ng ắ t ( Interrupt Vector Table). Mỗi một véctơ có 4 byte thể hiện địa chỉ (segment và offset) của chươ ng trình con dịch vụ ngắt. Các véctơ này mang những ý ngh ĩ a, chức năng khác nhau và đượ c định ngh ĩ a bở i kiến trúc của bộ xử lý. Ví dụ: véctơ 0 là lỗi chia 0, véctơ 3 là breakpoint (lệnh ngắt INT 1byte)…
Hình 3 - Ng ắt - Bảng véct ơ ng ắt
Một số véctơ đượ c dành cho các ng ắt ngoài. Trong PC, các véct ơ 8 đến 15 và 0x70 đến 0x77 đượ c dành cho phần cứng. Tất cả các véctơ đượ c truy cậ p thông qua lệnh ngắt INT 2byte, trong đó, byte thứ 2 chỉ ra số thứ tự của véctơ (ngắt). Phần mềm hệ thống thườ ng thiết lậ p các quy ướ c liên quan đến nhiều véctơ này. Ví dụ: PC BIOS sử dụng một số ngắt cho các d ịch vụ phần cứng và LINUX sử dụng ngắt INT 0x80 để gọi dịch vụ của kernel. Sau đây là một ví dụ về việc sử dụng ngắt INT 0x80 của Linux. - Bộ xử lý lưu lại giá tr ị hiện thờ i của thanh ghi bộ đếm chươ ng trình Program Counter (PC) và Code Segment (CS) vào ng ăn xế p stack cùng vớ i từ điều khiển tr ạng thái bộ xử lý Proccesor Status Word (PSW).
Võ Duy Thành –
[email protected]
3 / 6
Polling v.s Interrupt
- Byte thứ 2 trong câu lệnh INT là một chỉ số trong bảng véctơ ngắt để từ đó tìm đượ c địa chỉ của chươ ng trình con dịch vụ ngắt (ISR). Bộ xử lý nạ p địa chỉ này vào thanh ghi PC và CS và vi ệc thực hiện chươ ng trình con đượ c thực hiện từ điểm này.
Hình 4 - Ng ắt và hoạt động của ng ắt
- K ết thúc của ISR là câu l ệnh IRET (Interrupt Return). Nó giải phóng PC và CS để nạ p lại giá tr ị của chươ ng trình chính và thực hiện tiế p lệnh tiế p theo sau lệnh INT. Lệnh INT cũng tươ ng tự như lệnh gọi chươ ng trình con CALL nhưng có đôi chút khác biệt: trong khi địa chỉ đích của lệnh CALL đượ c nhúng vào trong câu lệnh đó thì vớ i INT, ta không c ần quan tâm đến địa chỉ của ISR. Địa chỉ của nó nầm trong bảng véctơ ngắt. Đây là một điểm thuận lợ i cho việc truyền thông giữa chươ ng trình đượ c biên dịch và chươ ng trình đượ c tải, ví dụ như chươ ng trình ứng dụng và hệ điều hành. Các ngắt ngoài có cách th ức thực hiện như thể hiện trong hình 5. Một thiết bị bên ngoài đưa ra một “yêu cầu ng ắ t” Interrupt Request ( IRQ). Khi bộ xử lý phản ứng lại bằng một xác nhận “chấ p nhận ng ắt ” Interrupt Acknowledge ( IAK ), thiết bị đó sẽ gửi số thứ tự của véctơ ngắt lên bus dữ liệu. Bộ xử lý sau đó sẽ thiết lậ p một lệnh ngắt INT vớ i chỉ số véctơ ngắt đã đượ c cung cấ p.
Võ Duy Thành –
[email protected]
4 / 6
Polling v.s Interrupt
Hình 5 – Ng ắt cứ ng
Trong thực tế, hầu hết các hệ thống đều sát nhậ p thêm một thiết bị ngoại vi đặc biệt đượ c gọi là bộ đ iề u khiể n ng ắt Interrupt Controller để quản lý các công việc chi tiết chẳng hạn như gửi chỉ số của véctơ ngắt lên bus dữ liệu vào đúng thờ i điểm cần thiết. Kiến trúc PC bao g ồm 2 bộ điều khiển ngắt 8259, mỗi một bộ có thể quản lý đượ c 8 ngắt. Mỗi một bộ 8259 có một cơ chế quản lý ngắt theo kiểu ưu tiên. Do đó, một thiết bị quan tr ọng sẽ đượ c ưu tiên hơ n thiết bị khác ít quan tr ọng hơ n. Ngắt có thể đượ c kích hoạt hoặc bị vô hiệu hoá. Ở cấ p độ của bộ xử lý, ngắt có thể đượ c kích hoạt hoặc vô hiệu hoá thông qua câu lệnh STI và CLI. Các ng ắt có thể đượ c kích hoạt hoặc vô hiệu một cách có chọn lọc ở cả bộ điều khiển ngắt 8259 hay ở chính thiết bị đó. Trên thực tế, vi ệc kích hoạt và vô hi ệu ng ắt chính là đ iể m mấ u chố t để thi ế t k ế và thự c thi một phần mềm thờ i gian thự c. Cũng không có gì đáng ngạc nhiên khi nói r ằng ngắt không đồng bộ có những vấn đề đáng bàn của nó. Để ý một ứng dụng thu thậ p dữ liệu dựa trên bộ A/D đa kênh như trên hình 6. Cứ mỗi khi bộ chuyển đổi A/D thu thậ p một tậ p hợ p dữ liệu trên các kênh, nó ng ắt bộ xử lý. Chươ ng trình con dịch vu ngắt đọc dữ liệu và cất vào bộ nhớ đệm, nơ i mà chươ ng trình khác (còn gọi là chươ ng trình nền) sẽ tiế p tục xử lý.
Hình 6 – Ví d ụ về ng ắt Võ Duy Thành –
[email protected]
5 / 6
Polling v.s Interrupt
Hoạt động điều khiển ngắt cho phép chúng ta phản ứng lại A/D một cách nhanh chóng trong khi bộ nhớ đệm tách chươ ng trình nền khỏi nguồn dữ liệu, ví dụ, chươ ng trình nền không cần quan tâm đến dữ liệu đượ c từ đâu mà có đượ c. Bây giờ hãy xem đến đoạn mã lệnh đượ c ghi trong hình 6. Giả thiết chỉ là thí nghiệm, chúng ta cung c ấ p một tín hiệu biến đổi liên tục vào cả kênh 5 và 6. Đồng thờ i, giả thiết r ằng chươ ng trình sẽ không bị “fail” khi đang thực hiện đo tín hiệu đồng nhất. Trong thực tế, chươ ng trình như đã viết chắc chắn sẽ bị “fail” bở i vì một ngắt có thể xảy ra trong khi cậ p nhật biến Cur_temp và cậ p nhật biến Set_temp vớ i k ết quả là giá tr ị của biến Cur_temp đượ c cậ p nhật từ tậ p hợ p dữ liệu cũ tr ướ c đó, còn giá tr ị của biến Set_temp đượ c cậ p nhật từ tậ p hợ p dữ liệu hiện thờ i. Như vậy, khi tín hiệu đầu vào thay đổi theo thờ i gian và các t ậ p hợ p dữ liệu đượ c tách r ời nhau ở các thờ i gian xác định, giá tr ị các biến sẽ khác nhau và do đó, chươ ng trình sẽ “fail”. Đây chính là b ản chất của vấn đề lậ p trình thờ i gian thực. C ần phải quản lý các ng ắt không đồng bộ để chúng không x ả y ra vào nhữ ng thờ i đ i ểm không thích hợ p. Có một giải pháp, dù không hay cho lắm, để giải quyết vấn đề này. Ta có th ể dùng một lệnh vô hiệu hoá ngắt (CLI) tr ướ c khi cậ p nhật biến Cur_temp và kích hoạt ngắt bằng lệnh STI sau khi cậ p nhật biến Set_temp. Việc làm này giúp các ng ắt tránh khỏi phiền phức của việc cậ p nhật liên tục như đã đề cậ p. Có vẻ như chúng ta đã sáng suốt khi sử dụng các lệnh CLI và STI nh ư một chìa khoá cho một giải pháp đúng đắn, nhưng nếu chỉ đơ n giản là r ải các lệnh CLI và STI trong code c ủa chươ ng trình thì cũng chẳng khác gì việc sử dụng các lệnh “go to” và các bi ến toàn cục.
Võ Duy Thành –
[email protected]
6 / 6