Tải bản đầy đủ (.docx) (19 trang)

lập trình nhân linux interrupts

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (297.75 KB, 19 trang )

<span class="text_page_counter">Trang 1</span><div class="page_container" data-page="1">

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

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

<b>Ngắt là gì?</b>

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ì hỗn hoặc vơ hiệu hóa tạm thờingắt:

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

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

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

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

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

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

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 ngồ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.

</div><span class="text_page_counter">Trang 2</span><div class="page_container" data-page="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ìhỗ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/hỗn lại được.

<b>Ngoại lệ</b>

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

<b>o Lỗio Bẫyo Hủy bỏ</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).

<b>Câu hỏi: Thuật ngữ ngắt</b>

Đố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)

</div><span class="text_page_counter">Trang 3</span><div class="page_container" data-page="3">

 Breakpoint: Exception, Trap, Fault

<b>Khái niệm phần cứng</b>

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

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

</div><span class="text_page_counter">Trang 4</span><div class="page_container" data-page="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.

<b>Ghi chú</b>

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>Bộ điều khiển ngắt trong hệ thống SMP</b>

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.

</div><span class="text_page_counter">Trang 5</span><div class="page_container" data-page="5">

<b>Kiểm sốt ngắt </b>

Để đồ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 số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)

</div><span class="text_page_counter">Trang 6</span><div class="page_container" data-page="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.

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

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

<b>Câu trả lời:</b>

 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:

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

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. <b>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ơ</b>

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

<b>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</b>

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. <b>Ngắt có thể bị vơ hiệu hóa ở cấp độ bộ điều khiển ngắt: Đúng. Bộ điều</b>

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

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

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

</div><span class="text_page_counter">Trang 7</span><div class="page_container" data-page="7">

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

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.

</div><span class="text_page_counter">Trang 8</span><div class="page_container" data-page="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.

</div><span class="text_page_counter">Trang 9</span><div class="page_container" data-page="9">

<b>Địa chỉ xử lý ngắt</b>

Để 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.

<b>Ngăn xếp xử lý ngắt</b>

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ệ.

</div><span class="text_page_counter">Trang 10</span><div class="page_container" data-page="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

<b>Trở về từ trình xử lý ngắt</b>

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ỏ)

</div><span class="text_page_counter">Trang 11</span><div class="page_container" data-page="11">

3. set $idtr_addr=($idtr_entry>>48<<16)|($idtr_entry&0xffff): Tính tố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.

</div><span class="text_page_counter">Trang 12</span><div class="page_container" data-page="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.

<b>Ghi chú</b>

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 q trình xử lý ngắt, các hành động trì hỗ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ộ.

</div><span class="text_page_counter">Trang 13</span><div class="page_container" data-page="13">

<b>Các ngắt và ngoại lệ lồng nhau</b>

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:

</div><span class="text_page_counter">Trang 14</span><div class="page_container" data-page="14">

<b>Bối cảnh ngắt </b>

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)

<b>Hành động có thể trì hỗn</b>

Các hành động có thể trì hỗ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ì hỗ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 hồn tất.

Có hai loại hành động lớn có thể trì hỗ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ì hỗ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ìhỗ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ì hỗn từ trình xử lý ngắt.

</div><span class="text_page_counter">Trang 15</span><div class="page_container" data-page="15">

<b>Soft IRQs </b>

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ìhỗ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: <b><small>open_softirq()</small></b>

 Kích hoạt: <b><small>raise_softirq()</small></b>

 Tạm dừng: <b><small>local_bh_disable()</small></b>,<b><small>local_bh_enable()</small></b>. Sau khi được kích hoạt, hàm gọi lại <b><small>do_softirq()</small></b> 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á <b><small>MAX_SOFTIRQ_TIME</small></b> hoặc lập lịch lại quá <b><small>MAX_SOFTIRQ_RESTART</small></b> 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:

<small> HI_SOFTIRQ=0, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, BLOCK_SOFTIRQ, IRQ_POLL_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ,</small>

</div><span class="text_page_counter">Trang 16</span><div class="page_container" data-page="16">

<small> RCU_SOFTIRQ, </small><i><small>/* Preferable RCU should always be the last softirq */</small></i>

<small> NR_SOFTIRQS};</small>

<b>Ví dụ về tràn gói</b>

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 q 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.

<b>Hàng đợi công việc</b>

Hàng đợi công việc là một loại công việc bị trì hỗ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: <b><small>INIT_WORK</small></b>

<small></small> Kích hoạt: <b><small>schedule_work()</small></b>

</div><span class="text_page_counter">Trang 17</span><div class="page_container" data-page="17">

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

<b>Câu hỏi: Xử lý ngắt Linux </b>

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ì hỗn

<b>Câu trả lời: Khẩn cấp</b>

</div><span class="text_page_counter">Trang 18</span><div class="page_container" data-page="18">

<i><b>Ví dụ: </b></i>

Đâ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,

</div>

×