lập trình nhân linux interrupts

19 0 0
Tài liệu đã được kiểm tra trùng lặp
lập trình nhân linux interrupts

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Chúng cũng có thểđược nhóm thành hai loại khác dựa trên khả năng trì hoãn hoặc vô hiệu hóa tạm thờingắt: Synchronous Đồng bộ, được tạo bằng cách thực hiện một lệnh Asynchronous Không đ

Trang 1

Interrupts: NgắtMục tiêu bài giảng

 Ngắt và ngoại lệ (x86) Ngắt và ngoại lệ (Linux) Công việc có thể trì hoãn Bộ hẹn giờ

Ngắt là gì?

Ngắt là một sự kiện làm thay đổi luồng thực thi thông thường của chương trình vàcó thể được tạo ra bởi các thiết bị phần cứng hoặc thậm chí bởi chính CPU Khi xảy ragián đoạn, luồng thực thi hiện tại bị tạm dừng và trình xử lý ngắt sẽ chạy Sau khi trìnhxử lý ngắt chạy, luồng thực thi trước đó sẽ được tiếp tục.

Các ngắt có thể được nhóm thành hai loại dựa trên nguồn ngắt Chúng cũng có thểđược nhóm thành hai loại khác dựa trên khả năng trì hoãn hoặc vô hiệu hóa tạm thờingắt:

Synchronous (Đồng bộ), được tạo bằng cách thực hiện một lệnh

Asynchronous (Không đồng bộ), được tạo bởi một sự kiện bên ngoài

Maskable (có thể che giấu hoặc tạm dừng)o Có thể được bỏ qua

o Được báo hiệu qua chân INT

Non-maskable (không thể che giấu hoặc không thể tắt)o Không thể bỏ qua

o Được báo hiệu qua chân NMI

Các ngắt đồng bộ, thường được đặt tên là ngoại lệ, xử lý các điều kiện được chínhbộ xử lý phát hiện trong quá trình thực hiện lệnh Chia cho số 0 hoặc cuộc gọi hệ thốnglà những ví dụ về trường hợp ngoại lệ.

Các ngắt không đồng bộ, thường được đặt tên là các ngắt, là các sự kiện bên ngoàiđược tạo ra bởi các thiết bị I/O Ví dụ, card mạng tạo ra các ngắt để báo hiệu rằng gói đãđến.

Trang 2

Hầu hết các ngắt đều có thể tạm dừng được, có nghĩa là chúng ta có thể tạm thời trìhoãn việc chạy trình xử lý ngắt khi chúng ta vô hiệu hóa ngắt cho đến khi ngắt đượckích hoạt lại Tuy nhiên, có một số ngắt quan trọng không thể tắt/hoãn lại được.

Ngoại lệ

Có 2 nguồn cho các trường hợp ngoại lệ: Bộ xử lý phát hiện

o Lỗio Bẫyo Hủy bỏ

Bẫy là một loại ngoại lệ được báo cáo sau khi thực hiện lệnh trong đó phát hiệnngoại lệ EIP đã lưu là địa chỉ của lệnh sau lệnh gây ra bẫy (ví dụ: bẫy gỡ lỗi).

Câu hỏi: Thuật ngữ ngắt

Đối với mỗi thuật ngữ sau đây ở bên trái, hãy chọn tất cả các thuật ngữ từ bên phảimô tả chúng đúng nhất.

 Cơ quan giám sát (Watchdog)  Ngoại lệ (Exception) Phân trang theo yêu cầu (Demand

 Ngắt (Interrupt) Chia cho số không (Division by

 Tạm dừng (Maskable)

 Cuộc gọi hệ thống (System call)  Bẫy (Trap)

Trang 3

 Breakpoint: Exception, Trap, Fault

Khái niệm phần cứng

Bộ điều khiển ngắt lập trình

Thiết bị hỗ trợ ngắt có chân đầu ra được sử dụng để báo hiệu Yêu cầu ngắt Cácchân IRQ được kết nối với một thiết bị có tên Bộ điều khiển ngắt khả trình (PIC) đượckết nối với chân INTR của CPU.

PIC thường có một bộ cổng dùng để trao đổi thông tin với CPU Khi một thiết bịđược kết nối với một trong các dòng IRQ của PIC cần sự chú ý của CPU, luồng sau sẽxảy ra:

 Thiết bị tạo ra một ngắt trên chân IRQn tương ứng

 PIC chuyển đổi IRQ thành số vectơ và ghi nó vào cổng để CPU đọc PIC tăng một ngắt trên chân INTR của CPU

 PIC đợi CPU xác nhận một ngắt trước khi đưa ra một ngắt khác CPU xác nhận ngắt sau đó nó bắt đầu xử lý ngắt

Trang 4

Sau này sẽ xem CPU xử lý ngắt như thế nào Lưu ý rằng PIC theo thiết kế sẽ khôngtạo ra một ngắt khác cho đến khi CPU xác nhận ngắt hiện tại.

Ghi chú

Sau khi CPU xác nhận ngắt, bộ điều khiển ngắt có thể yêu cầu một ngắt khác, bấtkể CPU đã xử lý xong ngắt trước đó hay chưa Do đó, tùy thuộc vào cách hệ điềuhành điều khiển CPU mà có thể có các ngắt lồng nhau.

Bộ điều khiển ngắt cho phép từng dòng IRQ bị vô hiệu hóa riêng lẻ Điều này chophép đơn giản hóa thiết kế bằng cách đảm bảo rằng các bộ xử lý ngắt luôn được thực thituần tự.

Bộ điều khiển ngắt trong hệ thống SMP

Trong hệ thống SMP, chúng ta có thể có nhiều bộ điều khiển ngắt trong hệ thống.Ví dụ: trên kiến trúc x86, mỗi lõi có một APIC cục bộ được sử dụng để xử lý cácngắt từ các thiết bị được kết nối cục bộ như bộ định thời hoặc cảm biến nhiệt Sau đó, cóAPIC I/O được sử dụng để phân phối IRQ từ các thiết bị bên ngoài đến lõi CPU.

Trang 5

Kiểm soát ngắt

Để đồng bộ hóa quyền truy cập vào dữ liệu được chia sẻ giữa trình xử lý ngắt vàcác hoạt động đồng thời tiềm năng khác như khởi tạo trình điều khiển hoặc xử lý dữ liệutrình điều khiển, thường cần phải bật và tắt các ngắt theo cách được kiểm soát.

Điều này có thể được thực hiện ở nhiều cấp độ: Ở cấp độ thiết bị

o Bằng cách lập trình các thanh ghi điều khiển thiết bị Ở cấp độ PIC

o PIC có thể được lập trình để vô hiệu hóa một dòng IRQ nhất định Ở cấp độ CPU; ví dụ: trên x86, người ta có thể sử dụng các hướng dẫn sau: cli (Cờ ngắt Clear)

Trang 6

Không phải tất cả các kiến trúc đều hỗ trợ mức độ ưu tiên ngắt Cũng khó hỗ trợviệc xác định sơ đồ chung cho các ưu tiên ngắt cho các hệ điều hành sử dụngchung và một số hạt nhân (bao gồm cả Linux) không sử dụng các ưu tiên ngắt.Mặt khác, hầu hết các RTOS sử dụng mức độ ưu tiên ngắt vì chúng thường đượcsử dụng trong các trường hợp sử dụng hạn chế hơn, trong đó việc xác định mứcđộ ưu tiên ngắt sẽ dễ dàng hơn.

Câu hỏi: Khái niệm phần cứng

Khẳng định nào sau đây là đúng?

 CPU có thể bắt đầu xử lý một ngắt mới trước khi ngắt hiện tại kết thúc Ngắt có thể bị vô hiệu hóa ở cấp độ thiết bị

 Các ngắt có mức ưu tiên thấp hơn không thể ưu tiên các trình xử lý cho cácngắt có mức ưu tiên cao hơn

 Ngắt có thể bị vô hiệu hóa ở cấp độ bộ điều khiển ngắt

 Trên hệ thống SMP, cùng một ngắt có thể được định tuyến đến các CPUkhác nhau

Ngắt có thể bị vô hiệu hóa ở cấp độ CPU

Câu trả lời:

 CPU có thể bắt đầu xử lý một ngắt mới trước khi ngắt hiện tại kết thúc:

Đúng Điều này thường được gọi là lồng ngắt, trong đó ngắt có mức ưu tiên

cao hơn có thể làm gián đoạn việc xử lý ngắt có mức ưu tiên thấp hơn. Ngắt có thể bị vô hiệu hóa ở cấp độ thiết bị: Đúng Các thiết bị có thể có cơ

chế điều khiển để kích hoạt hoặc vô hiệu hóa khả năng tạo ra các ngắt. Các ngắt có mức ưu tiên thấp hơn không thể ưu tiên các trình xử lý cho các

ngắt có mức ưu tiên cao hơn: Sai Trong hầu hết các hệ thống ngắt, các ngắt

có mức ưu tiên cao hơn có thể ưu tiên các ngắt có mức ưu tiên thấp hơn. Ngắt có thể bị vô hiệu hóa ở cấp độ bộ điều khiển ngắt: Đúng Bộ điều

khiển ngắt thường có cơ chế cho phép hoặc vô hiệu hóa việc tạo ngắt.

 Trên hệ thống SMP, cùng một ngắt có thể được định tuyến đến các CPU

khác nhau: Đúng Điều này phổ biến trong các hệ thống đa xử lý đối xứng

(SMP), trong đó các ngắt có thể được phân phối trên nhiều CPU.

Trang 7

Ngắt có thể bị vô hiệu hóa ở cấp độ CPU: Đúng CPU thường có cơ chế

kích hoạt hoặc vô hiệu hóa việc xử lý ngắt tạm thời.

IDT có các đặc điểm sau:

 Nó được CPU sử dụng làm bảng nhảy khi một vectơ nhất định được kích hoạt Nó là một mảng gồm các mục 256 x 8 byte

 Có thể cư trú ở bất cứ đâu trong bộ nhớ vật lý Bộ xử lý định vị IDT bằng IDTR

Dưới đây chúng ta có thể tìm thấy bố cục vector IRQ của Linux 32 mục đầu tiênđược dành riêng cho các trường hợp ngoại lệ, vectơ 128 được sử dụng cho giao diện tòanhà và phần còn lại được sử dụng chủ yếu cho các trình xử lý ngắt phần cứng.

Trang 8

Trên x86, mục nhập IDT có 8 byte và được đặt tên là cổng Có thể có 3 loại cổng: Cổng ngắt, giữ địa chỉ của trình xử lý ngắt hoặc ngoại lệ Việc chuyển sang trình

xử lý sẽ vô hiệu hóa các ngắt có thể che được (cờ IF bị xóa).

 Cổng bẫy, tương tự như cổng ngắt nhưng nó không vô hiệu hóa các ngắt có thểche được trong khi chuyển sang trình xử lý ngắt/ngoại lệ.

 Cổng tác vụ (không được sử dụng trong Linux)Chúng ta hãy xem xét một số trường của mục nhập IDT:

 Bộ chọn phân đoạn, lập chỉ mục vào GDT/LDT để tìm điểm bắt đầu của đoạnmã nơi chứa trình xử lý ngắt

 Offset, offset bên trong đoạn mã T, đại diện cho loại cổng

 DPL, đặc quyền tối thiểu cần thiết để sử dụng nội dung phân đoạn.

Trang 9

Địa chỉ xử lý ngắt

Để tìm địa chỉ trình xử lý ngắt, trước tiên chúng ta cần tìm địa chỉ bắt đầu của đoạnmã nơi chứa trình xử lý ngắt Để làm điều này, chúng tôi sử dụng bộ chọn phân đoạn đểlập chỉ mục vào GDT/LDT nơi chúng tôi có thể tìm thấy bộ mô tả phân đoạn tương ứng.Điều này sẽ cung cấp địa chỉ bắt đầu được lưu trong trường 'cơ sở' Sử dụng địa chỉ cơsở và phần bù, bây giờ chúng ta có thể đi đến điểm bắt đầu của trình xử lý ngắt.

Ngăn xếp xử lý ngắt

Tương tự như việc chuyển điều khiển sang một hàm thông thường, việc chuyểnđiều khiển sang một trình xử lý ngắt hoặc ngoại lệ sử dụng ngăn xếp để lưu trữ thông tincần thiết để quay lại mã bị gián đoạn.

Như có thể thấy trong hình bên dưới, một ngắt sẽ đẩy thanh ghi EFLAGS trước khilưu địa chỉ của lệnh bị gián đoạn Một số loại ngoại lệ nhất định cũng khiến mã lỗi đượcđẩy lên ngăn xếp để giúp gỡ lỗi ngoại lệ.

Trang 10

 Lưu EFLAGS, CS, EIP vào ngăn xếp

 Lưu mã lỗi vào ngăn xếp trong trường hợp hủy bỏ Thực thi trình xử lý ngắt kernel

Trở về từ trình xử lý ngắt

Hầu hết các kiến trúc đều đưa ra các hướng dẫn đặc biệt để dọn sạch ngăn xếp vàtiếp tục thực thi sau khi trình xử lý ngắt đã được thực thi Trên x86 IRET được sử dụngđể trả về từ trình xử lý ngắt IRET tương tự như RET ngoại trừ việc IRETin tăng thêmESP thêm bốn byte (do các cờ trên ngăn xếp) và chuyển các cờ đã lưu vào thanh ghiEFLAGS.

Để tiếp tục thực thi sau khi bị gián đoạn, trình tự sau được sử dụng (x86): Bật mã lỗi (trong trường hợp hủy bỏ)

Trang 11

3 set $idtr_addr=($idtr_entry>>48<<16)|($idtr_entry&0xffff): Tính toán giá trịcủa $idtr_addr dựa trên giá trị của $idtr_entry theo công thức đã cho.

4 print (void*)$idtr_addr: In ra giá trị của $idtr_addr dưới dạng con trỏ.

5 (void *) 0xc15de780 <entry_SYSENTER_32>: Đây là đầu ra của lệnh trước đó,có thể là một địa chỉ cụ thể trong bộ nhớ.

6 set $idtr = 0xff801000: Lệnh này lại một lần nữa thiết lập giá trị mới cho $idtr.7 (void *) 0xc15de874 <entry_INT80_32>: Đây cũng là một địa chỉ cụ thể trong

bộ nhớ, có thể liên quan đến trình xử lý ngoại lệ cuộc gọi hệ thống.

Trang 12

8 monitor info registers: Đây là lệnh để hiển thị thông tin về các thanh ghi trongmáy tính.

Trong giai đoạn thứ hai, tất cả các trình xử lý của trình điều khiển thiết bị liên quanđến ngắt này sẽ được thực thi Vào cuối giai đoạn này, phương thức "kết thúc ngắt" củabộ điều khiển ngắt được gọi để cho phép bộ điều khiển ngắt xác nhận lại ngắt này Cácngắt bộ xử lý cục bộ được kích hoạt tại thời điểm này.

Ghi chú

Có thể một ngắt được liên kết với nhiều thiết bị và trong trường hợp này người tanói rằng ngắt được chia sẻ Thông thường, khi sử dụng các ngắt được chia sẻ,trình điều khiển thiết bị có trách nhiệm xác định xem ngắt có nhắm mục tiêu đếnthiết bị của nó hay không.

Cuối cùng, trong giai đoạn cuối của quá trình xử lý ngắt, các hành động trì hoãn bốicảnh ngắt sẽ được chạy Đôi khi chúng còn được gọi là "nửa dưới" của ngắt (nửa trên làphần xử lý ngắt chạy với các ngắt bị vô hiệu hóa) Tại thời điểm này, các ngắt được kíchhoạt trên bộ xử lý cục bộ.

Trang 13

Các ngắt và ngoại lệ lồng nhau

Linux từng hỗ trợ các ngắt lồng nhau nhưng điều này đã bị loại bỏ một thời giantrước để tránh các giải pháp ngày càng phức tạp cho các vấn đề về stackoverflow - chỉcho phép một cấp độ lồng nhau, cho phép nhiều cấp độ lồng nhau đến một độ sâu ngănxếp hạt nhân nhất định, v.v.

Tuy nhiên, vẫn có thể có sự lồng ghép giữa các ngoại lệ và các ngắt nhưng các quytắc khá hạn chế:

 Một ngoại lệ (ví dụ: lỗi trang, lệnh gọi hệ thống) không thể tránh được sự giánđoạn; nếu điều đó xảy ra thì đó được coi là một lỗi

 Một ngắt có thể ngăn chặn một ngoại lệ

 Một ngắt không thể chặn trước một ngắt khác (trước đây có thể xảy ra)Sơ đồ dưới đây cho thấy các tình huống lồng nhau có thể xảy ra:

Trang 14

Bối cảnh ngắt

Trong khi một ngắt được xử lý (từ lúc CPU chuyển sang bộ xử lý ngắt cho đến khibộ xử lý ngắt quay trở lại - ví dụ: IRET được phát hành), người ta nói rằng mã đó chạytrong "ngữ cảnh ngắt".

Mã chạy trong ngữ cảnh ngắt có các thuộc tính sau: Nó chạy do IRQ (không phải là ngoại lệ)

 Không có bối cảnh quy trình được xác định rõ ràng liên quan

 Không được phép kích hoạt chuyển đổi ngữ cảnh (không có quyền truy cập chếđộ ngủ, lịch trình hoặc bộ nhớ người dùng)

Hành động có thể trì hoãn

Các hành động có thể trì hoãn được sử dụng để chạy các hàm gọi lại sau này Nếucác hành động có thể trì hoãn được lên lịch từ trình xử lý ngắt, hàm gọi lại liên quan sẽchạy sau khi trình xử lý ngắt hoàn tất.

Có hai loại hành động lớn có thể trì hoãn: những hành động chạy trong ngữ cảnhkhông bị gián đoạn và những hành động chạy trong ngữ cảnh tiến trình.

Mục đích của các hành động có thể trì hoãn ngữ cảnh ngắt là để tránh thực hiện quánhiều công việc trong hàm xử lý ngắt Chạy quá lâu với các ngắt bị vô hiệu hóa có thểgây ra những tác động không mong muốn như độ trễ tăng lên hoặc hiệu suất hệ thốngkém do thiếu các ngắt khác (ví dụ: làm mất các gói mạng vì CPU không phản ứng kịpthời để loại bỏ các gói khỏi giao diện mạng và bộ đệm card mạng đã đầy).

Các hành động có thể trì hoãn có các API để: khởi tạo một phiên bản, kích hoạthoặc lên lịch hành động và che/vô hiệu hóa và vạch mặt/cho phép thực thi chức năng gọilại Cái sau được sử dụng cho mục đích đồng bộ hóa giữa hàm gọi lại và các ngữ cảnhkhác.

Thông thường, trình điều khiển thiết bị sẽ khởi tạo cấu trúc hành động có thể trìhoãn trong quá trình khởi tạo phiên bản thiết bị và sẽ kích hoạt/lên lịch hành động có thểtrì hoãn từ trình xử lý ngắt.

Trang 15

Soft IRQs

Soft IRQs là thuật ngữ được sử dụng cho cơ chế cấp thấp thực hiện công việc trìhoãn từ các trình xử lý ngắt nhưng vẫn chạy trong ngữ cảnh ngắt.

Soft IRQ APIs:

 Khởi tạo: open_softirq()

 Kích hoạt: raise_softirq()

 Tạm dừng: local_bh_disable(),local_bh_enable() Sau khi được kích hoạt, hàm gọi lại do_softirq() sẽ chạy: sau một trình xử lý ngắt hoặc

 từ chuỗi hạt nhân ksoftirqd

Vì các phần mềm có thể tự sắp xếp lại lịch trình hoặc các ngắt khác có thể xảy rakhiến chúng sắp xếp lại lịch trình, nên chúng có khả năng dẫn đến tình trạng chết đóiquy trình (tạm thời) nếu không thực hiện kiểm tra Hiện tại, nhân Linux không cho phépchạy các irq mềm quá MAX_SOFTIRQ_TIME hoặc lập lịch lại quá MAX_SOFTIRQ_RESTART lầnliên tiếp.

Khi các giới hạn này đạt đến một luồng hạt nhân đặc biệt, ksoftirqd sẽ được đánhthức và tất cả phần còn lại của các irq mềm đang chờ xử lý sẽ được chạy từ ngữ cảnhcủa luồng hạt nhân này.

Việc sử dụng irq mềm bị hạn chế, chúng được sử dụng bởi một số hệ thống con cóyêu cầu về độ trễ thấp và tần suất cao:

HI_SOFTIRQ=0, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, BLOCK_SOFTIRQ, IRQ_POLL_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ,

Trang 16

RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */

NR_SOFTIRQS};

Ví dụ về tràn gói

Video màn hình sau đây sẽ xem xét điều gì xảy ra khi chúng ta làm ngập hệ thốngvới một số lượng lớn gói tin Vì ít nhất một phần của quá trình xử lý gói đang diễn ratrong softirq nên chúng ta nên kỳ vọng CPU sẽ dành phần lớn thời gian để chạy cácsoftirq nhưng phần lớn thời gian đó sẽ nằm trong ngữ cảnh của luồng ksoftirqd.

Hàng đợi công việc

Hàng đợi công việc là một loại công việc bị trì hoãn chạy trong ngữ cảnh quy trình.Chúng được triển khai trên các luồng kernel.

API hàng đợi công việc:  Khởi tạo: INIT_WORK

 Kích hoạt: schedule_work()

Trang 17

o chạy trong bối cảnh quá trình

Câu hỏi: Xử lý ngắt Linux

Giai đoạn xử lý ngắt nào sau đây diễn ra trong khi các ngắt bị vô hiệu hóa ở cấpđộ CPU?

 Khẩn cấp Tức thời Trì hoãn

Câu trả lời: Khẩn cấp

Trang 18

Ví dụ:

Đây là một module kernel Linux, nó sẽ tạo ra một hàng đợi công việc và đăng kýmột trình xử lý ngắt Khi một ngắt từ bàn phím xảy ra, mã quét từ bàn phím sẽ được đọcvà một công việc sẽ được đưa vào hàng đợi công việc Công việc này sau đó sẽ được xửlý và in ra mã quét và trạng thái của phím (được nhấn hay thả) Khi module này được gỡbỏ khỏi kernel, ngắt sẽ được giải phóng.

#include <linux/kernel.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/workqueue.h>#include <linux/interrupt.h>#include <asm/io.h>

#define MY_WORK_QUEUE_NAME "WQsched.c"static struct workqueue_struct *my_workqueue;struct my_work {

struct work_struct work; unsigned char scancode;};

static struct my_work task;

static void got_char(struct work_struct *work){

struct my_work *my_work = container_of(work, struct my_work, work); printk(KERN_INFO "Scan Code %x %s.\n",

(int)my_work->scancode & 0x7F,

Ngày đăng: 08/05/2024, 15:56

Tài liệu cùng người dùng

Tài liệu liên quan