Tổng quan về Linux
Giới thiệu tổng quan về Linux
Linux là một từ gọi chung của nhiều biến thể Hệ điều hành được phát triển bằng cách sử dụng nhân (kernel) Linux do Linus Torvalds tạo ra như một giải pháp mã nguồn mở thay thế.
Mã nguồn mở có nghĩa là bất kỳ ai cũng được cấp phép tự do để sử dụng, sao chép, nghiên cứu hoặc thay đổi phần mềm theo bất kỳ cách nào Mã nguồn, là tập hợp các hướng dẫn cho máy tính biết cách hoạt động ra sao, được chia sẻ công khai để khuyến khích sự phát triển liên tục.
Việc áp dụng nhân Linux này đã tạo ra một bộ nguồn (source) Hệ điều hành không cần mua để sử dụng và cài đặt Điều này đối lập với mã độc quyền (proprietary code), nơi mã nguồn bị che dấu với người dùng và bị hạn chế sử dụng để sao chép theo luật. Linux có thể được cài đặt trên máy tính cá nhân và trở thành một trạm làm việc hoặc sử dụng trên các máy chủ lớn Có thể được sử dụng với mục đích thương mại trong các môi trường tính toán và truyền tin, cũng như được sử dụng để giảng dạy về hệ điều hành và lập trình hệ điều hành trong các trường đại học.
1.1.1 Lịch sử phát triển của hệ điều hành Linux
Năm 1991 Linus Torvalds, sinh viên của đại học tổng hợp Helsinki, Phần Lan, bắt đầu xem xét Minix, một phiên bản của Unix làm ra với mục đích nghiên cứu cách tạo ra một hệ điều hành Unix chạy trên máy PC với bộ vi xử lý Intel 80386 sử dụng với mục đích chủ yếu về học thuật.
Ngày 25/8/1991, Linus cho ra version 0.01 và thông báo trên comp.os.minix của Internet về dự định của mình về Linux.
Tháng 1/1992, Linus cho ra version 0.12 với shell và C compiler Linus không cần Minix nữa để recompile hệ điều hành của mình Linus đặt tên hệ điều hành của mình là Linux.
Năm 1994, phiên bản chính thức 1.0 được phát hành.
Ngày nay, Linux được phân ra làm nhiều nhánh như: Ubuntu, Linux Mint, Fedora… nhưng thông dụng nhất hiện nay đang là Ubuntu.
1.1.2 Ưu và nhược điểm của hệ điều hành Linux Ưu điểm:
Bản quyền: Là nền tảng mã nguồn mở và miễn phí Với hệ điều hành này, bạn không cần phải bỏ phí mua bản quyền mà có thể sử dụng đầy đủ các tính năng.Bao gồm các ứng dụng văn phòng OpenOffice và LibreOffice.
Tính bảo mật: Tất cả các phần mềm độc hại như virus, mã độc… đều không thể hoạt động trên Linux Do đó, độ bảo mật của hệ điều hành rất cao.
Tính linh hoạt: Người dùng còn có thể chỉnh sửa hệ điều hành theo nhu cầu sử dụng của mình Đây chính cơ hội lý tưởng cho các lập trình viên cũng như các nhà phát triển.
Hoạt động “mượt” trên các máy tính có cấu hình yếu: Với Linux, khi nâng cấp lên phiên bản mới, các máy tính có cấu hình yếu vẫn sẽ được nâng cấp và hỗ trợ thường xuyên – tức chất lượng hoạt động vẫn trơn tru và ổn định.
Số lượng ứng dụng hỗ trợ trên Linux còn rất hạn chế.
Một số nhà sản xuất không phát triển driver hỗ trợ nền tảng Linux.
Khó làm quen, đặc biệt nếu đã quá quen thuộc với Windows thì khi chuyển sang Linux sẽ cần một khoảng thời gian để làm quen nó.
1.1.3 Kiến trúc của hệ điều hành Linux
Figure 1 : Kiến trúc của hệ điều hành Kernel
Kernel: Đây là phần quan trọng và được ví như trái tim của hệ điều hành, phần kernel chứa các module, thư viện để quản lý và giao tiếp với phần cứng và các ứng dụng. Shell: Shell là một chương trình có chức năng thực thi các lệnh từ người dùng hoặc từ các ứng dụng - tiện ích yêu cầu chuyển đến cho Kernel xử lý.
Applications: Là các ứng dụng và tiện ích mà người dùng cài đặt trên Server Ví dụ:ftp, samba, Proxy, …
Giới thiệu về Linux Kernel
Figure 2 : Kiến trúc của Linux kernel
Dựa vào chức năng của hệ điều hành, Linux Kernel chia thành 6 thành phần:
Process Management: có nhiệm vụ quản lý tiến trình.
Memory Management: có nhiệm vụ quản lý bộ nhớ.
Device Management: có nhiệm vụ quản lý thiết bị.
File system Management: quản lý dữ liệu trên thiết bị lưu trữ (ổ cứng).
Network Management: quản lý gói tin theo mô hình TCP/IP.
System call interface: cung cấp dịch vụ sử dụng phần cứng cho các tiến trình.
Quản lý thiết bị (Device management)
Quản lý thiết bị bao gồm các “driver” và mỗi driver chịu trách nhiệm điều khiển, giám sát, trao đổi dữ liệu với một thiết bị.
Driver là một trình điều khiển có vai trò điều khiển, quản lý, giám sát một thực thể nào đó.Một thành phần phần cứng có thể được điều khiển bởi một driver hoặc được điều khiển bởi một thành phần phần cứng khác có driver của thành phần phần cứng đó quản lý Driver gồm các lệnh có chức năng giúp CPU tương tác với thiết bị như chuột, bàn phím Tuy nhiên các thiết bị này sẽ không được trực tiếp nối với CPU, do đó các thiết bị này sẽ được kết nối với CPU thông qua 1 thiết bị khác được gọi là device controller và mỗi device controller sẽ có driver của riêng mình Đứng từ góc độ của CPU, bộ điều khiển cũng chỉ là một thiết bị Do đó, cần có driver hướng dẫn CPU làm việc với bộ điều khiển Driver này được gọi là bus driver Còn driver hướng dẫn CPU làm việc với thiết bị thì được gọi là device driver.
Figure 3: Tương tác giữa thiết bị và driver
Các device controller thông thường được kết nối với CPU thông qua đường bus (PCI, IDE, USB, SPI, …) Trong vi điều khiển, CPU và các device controller thường được thiết kế trên một chip Điều này cho phép giảm kích thước và giá thành, phù hợp với phát triển hệ thống nhúng Mà về mặt nguyên tắc, sẽ không có gì khác biệt đối lớn đối với các driver trên các hệ thống máy tính cá nhân
Các bus driver cung cấp giao diện đặc tả cho các giao thức phần cứng tương ứng Nó nằm ở tầng dưới cùng trong mô hình phân lớp phần mềm của hệ điều hành Nằm trên nó là các device driver thực sự để vận hành các thiết bị, mang đặc trưng của từng thiết bị xác định Ngoài ra, mục đích quan trọng của các driver thiết bị là cung cấp một giao diện trừu tường hóa cho người sử dụng, tức là cung cấp một giao diện lên tầng trên của hệ điều hành Một cách tổng quan, một driver sẽ bao gồm 2 phần quan trọng: a) giao tiếp với thiết bị (Device-specific) b) giao tiếp với hệ điều hành (OS-specific)
Thành phần này cung cấp cho hệ điều hành các dịch vụ đọc/ghi dữ liệu của thiết bị. Điều này cho phép chúng ta xây dựng hệ điều hành độc lập với cấu trúc của thiết bị. Device specific
Thành phần này chứa các lệnh hướng dẫn CPU điều khiển thiết bị, giám sát thiết bị, trao đổi dữ liệu với thiết bị Chúng ta sử dụng datasheet của thiết bị để xây dựng thành phần này Datasheet là một tài liệu được cung cấp bởi nhà sản xuất thiết bị Nó mô tả sơ đồ khối chức năng, nguyên lý hoạt động, hiệu suất hoạt động, đặc tính điện của thiết bị và đặc biệt là bản đồ thanh ghi (register map).
Bus driver cung cấp interface thể hiện cho các phần cứng tương ứng Nó nằm ở tầng cuối cùng trong mô hình phân lớp hệ điều hành Dưới bus driver là hardware và trên nó là device driver.
Protocol abstraction: Thành phần này che giấu đi sự phức tạp của các giao thức trên bus, cung cấp các dịch vụ cho device driver sử dụng Ví dụ như đọc/ghi một thanh ghi nào đó của thiết bị.
Protocol specific: Thành phần này chứa các lệnh hướng dẫn CPU làm việc với bộ điều khiển, giúp đọc/ghi dữ liệu trên bus Nó cũng được xây dựng dựa trên datasheet của bộ điều khiển.
Hệ thống I/O
Phân loại các thiết bị I/O
Một trong những công việc quan trọng của hệ điều hành là quản lý các thiết bị I/O khác nhau bao gồm chuột, bàn phím, touch pad, ổ đĩa, bộ điều hợp màn hình, thiết bị USB, màn hình được ánh xạ bit, đèn LED, bộ chuyển đổi tương tự sang kỹ thuật số, Bật / công tắc tắt, kết nối mạng, I / O âm thanh, máy in
Tại sao lại cần có I/O?
Cần có hệ thống I / O để nhận yêu cầu I / O của ứng dụng và gửi đến thiết bị vật lý, sau đó nhận bất kỳ phản hồi nào từ thiết bị và gửi đến ứng dụng(Nói một cách khác: Thiết bị đầu vào cung cấp đầu vào cho một máy tính, trong khi các thiết bị đầu ra cung cấp một cách cho một máy tính để dữ liệu đầu ra để giao tiếp với người dùng hoặc máy tính khác I / O thiết bị là một thiết bị với cả hai chức năng).Dựa vào lượng dữ liệu mỗi lần thiết bị trao đổi với CPU, thiết bị được chia làm 3 loại:
2.1.1 Thiết bị khối (Đĩa từ, băng từ) (block devices):
+ là thiết bị mà trình điều khiển giao tiếp bằng cách gửi toàn bộ khối dữ liệu Ví dụ, đĩa cứng, máy ảnh USB, Disk-On-Key
+ tương ứng với các tập tin đặc biệt trong chế độ khối (Block Mode) Các tập tin này tương ứng với các thiết bị ngoại vi có cấu trúc dạng khối như ổ đĩa, có kiểu truy cập bằng cách cung cấp một số khối đọc hoặc ghi Các thao tác nhập/xuất này được thực hiện thông qua một vùng đệm (Buffer Cache) và có thể truy nhập trực tiếp tới từng khối (Block) trên thiết bị.
+ Thông tin được lưu trữ có kích thước cố định và địa chỉ riêng
+ Có thể đọc ghi một khối độc lập với khối khác.
+ Tồn tại thao tác định vị thông tin (seek).
2.1.2 Thiết bị ký tự (Máy in, Bàn phím, chuột, )( Character devices):
+ tương ứng với các tập tin đặc biệt trong chế độ kí tự (Character Mode): Các tập tin này tương ứng với các thiết bị ngoại vi không có cấu trúc, chẳng hạn như các cổng song song hoặc nối tiếp mà trên đó dữ liệu có thể được đọc và ghi theo từng byte hoặc dòng byte
+ Chấp nhận luồng ký tự, không có cấu trúc khối
+ Không có thao tác định vị thông tin.
2.1.3 Thiết bị mạng (NIC card, Wifi chip):
Lượng dữ liệu nhỏ nhất mà CPU và thiết bị trao đổi với nhau là một gói tin, gồm nhiều byte Gói tin có kích thước không cố định Thông thường, network device là các thiết bị mạng.
Tổ chức các hệ thống nhập/xuất và chức năng
Hệ thống nhập/xuất chia thành 5 lớp với các chức năng riêng và có thể giao tiếp với các lớp khác.
Tiến trình người dùng (User process) Định dạng và thực hiện lời gọi nhập/xuất Chương trình nhập/xuất độc lập thiết bị
(Device – Independent software) Đặt tên, bảo vệ, tổ chức khối, tổ chức bộ đệm, cấp phát…
Chương trình điều khiển thiết bị (Devices driver)
Thiết lập các thanh ghi và kiểm tra trạng thái thiết bị
Chương trình kiểm soát ngắt (Interrupt handles)
Thông báo cho chương trình điều khiển thiết bị khi thao tác nhập/xuất hoàn tất Phần cứng (Hardware) Thực hiện thao tác nhập/xuất
Table 1: Tổ chức và chức năng hệ thống nhập xuất
Ví dụ tiến trình người dùng muốn đọc một khối dữ liệu trên đĩa sẽ gửi yêu cầu nhập/xuất đến chương trình nhập/xuất độc lập thiết bị Chương trình này sẽ tìm kiếm trong bộ đệm nhập/xuất, nếu khối cần đọc chưa có trong bộ đệm, nó sẽ gọi chương trình điều khiển thiết bị Chương trình điều khiển thiết bị gửi yêu cầu đến đĩa cứng và tiến trình người dùng sẽ tạm ngưng cho đến khi thao tác đọc đĩa hoàn tất, đĩa sẽ phát sinh một ngắt thông báo đã đọc xong, gửi tín hiệu ngắt cho chương trình kiểm soát ngắt Chương trình kiểm soát ngắt ghi nhận trạng thái của thiết bị và đánh thức tiến trình của người dùng để tiếp tục thực hiện.
Các phương pháp điều khiển I/O
2.3.1 Điều khiển bằng chương trình (Programmed I/O)
Nguyên tắc: o CPU trực tiếp điều khiển I/O thông qua chương trình của người lập trình. Các tín hiệu điều khiển I/O:
Tín hiệu điều khiển I/O Chức năng
Tín hiệu điều khiển (Control) Kích hoạt và khởi động thiết bị ngoại vi Tín hiệu kiểm tra (Test) Kiểm tra trạng thái thiết bị ngoại vi Tín hiệu điều khiển đọc (Read) CPU nhận dữ liệu từ thiết bị ngoại vi thông qua thanh ghi đệm dữ liệu Tín hiệu điều khiển ghi (Write) Dữ liệu chuyển đến thiết bị ngoại vi thông qua thanh ghi đệm và bus dữ liệu
Table 2 : Tín hiệu điều khiển I/O và chức năng
Hoạt động: o CPU yêu cầu thao tác với thiết bị. o CPU kiểm tra các bit trạng thái:
Nếu chưa sẵn sàng thì quay lại kiểm tra.
Nếu sẵn sàng thì chuyển sang trao đổi dữ liệu.
Sau khi gửi yêu cầu I/O, CPU phải đợi trạng thái sẵn sàng của thiết bị mà không thực hiện một chương trình khác, do đó gây tiêu tốn thời gian của CPU.
2.3.2 Điều khiển bằng ngắt (Interrupt Driven I/O)
CPU phát sinh một lệnh I/O đến các thiết bị I/O, sau đó tiếp tục việc xử lý cho đến khi nhận được một ngắt từ thiết bị I/O báo là đã hoàn tất nhập xuất, CPU tạm ngưng việc xử lý hiện tại để chuyển qua xử lý ngắt.
Các phương pháp nối ghép ngắt o Sử dụng nhiều đường yêu cầu ngắt
Mỗi module I/O được nối với một đường yêu cầu ngắt.
CPU phải có nhiều đường tín hiệu yêu cầu ngắt.
Hạn chế số lượng module I/O.
Các đường ngắt được quy định mức ưu tiên. o Hỏi vòng bằng phần mềm
CPU thực hiệu hỏi lần lượt từng module I/O.
Thứ tự các module được hỏi vòng chính là thứ tự ưu tiên. o Hỏi vòng bằng phần cứng
CPU phát tín hiệu chấp nhận ngắt (INTA) đến module I/O đầu tiên. Nếu module I/O đó không gây ra ngắt thì nó gửi tín hiệu đến module kế tiếp cho đến khi xác định được module gây ngắt.
Thứ tự các module I/O kết nối trong chuỗi xác định thứ tự ưu tiên. o Sử dụng bộ điều khiển ngắt lập trình được PIC
PIC có nhiều đường vào yêu cầu ngắt có quy định mức ưu tiên. PIC chọn một yêu cầu ngắt không bị cấm có mức ưu tiên cao nhất gửi tới CPU.
2.3.3 Truy cập bộ nhớ trực tiếp DMA (Direct Memory Access)
Xét quá trình đọc đĩa : CPU gửi cho bộ điều khiển đĩa các thông số : địa chỉ trên đĩa của khối, địa chỉ trong bộ nhớ RAM, số Byte cần đọc, sau đó CPU sẽ thực hiện công việc khác Bộ điều khiển sẽ đọc khối trên đĩa, từng bit cho đến khi toàn bộ khối được đưa vào buffer của bộ điều khiển Tiếp theo bộ điều khiển sẽ phát ra một ngắt để báo cho CPU là đã hoàn tất CPU lấy dữ liệu trong buffer chuyển vào RAM bằng cách tạo vòng lặp lần lượt từng byte ( lãng phí thời gian của CPU )
Bộ điều khiển có thêm khả năng truy xuất bộ nhớ trực tiếp (DMA) : Sau khi bộ điều khiển đọc toàn bộ dữ liệu từ thiết bị vào buffer thì bộ điều khiển sẽ chuyển byte đầu vào RAM tại địa chỉ được mô tả bởi địa chỉ bộ nhớ DMA Sau đó nó tăng địa chỉ DMA và giảm số bytes phải chuyển Quá trình này lặp lại cho tới khi số bytes phải chuyển bằng 0, và bộ điều khiển tạo một ngắt Như vậy bộ điều khiển tự chuyển khối vào trong bộ nhớ chính RAM.
Các kiểu thực hiện DMA: o Block - transfer DMA: DMAC(DMA Controller) sử dụng bus để truyền cả khối dữ liệu. o Cycle Stealing DMA: DMAC yêu cầu CPU treo tạm thời từng chu kỳ bus, DMAC chiếm bus thực hiện truyền một từ dữ liệu. o Transparent DMA: DMAC nhận biết những chu kỳ nào CPU không sử dụng bus thì chiếm bus để trao đổi một từ dữ liệu.
Giao tiếp thiết bị I/O với hệ điều hành
o Sau khi hệ điều hành gửi yêu cầu ra thiết bị ngoại vị, hệ điều hành cần phải biết thiết bị ngoại vi hoàn thành yêu cầu vào ra hay gặp lỗi Điều này có thể thực hiện theo 2 phương pháp ngắt và thăm dò.
Interrupt I/O là một quá trình truyền dữ liệu (data transfer) trong đó thiết bị gắn ngoài (external device) hoặc thiết bị ngoại vi (peripheral) thông báo cho CPU rằng nó đã sẵn sàng để giao tiếp và yêu cầu sự chú ý của CPU.
2.4.2 Xử lý ngắt: o Ghi nhận đặc trưng sự kiện gây ngắt vào ô nhớ cố định o Ghi nhận trạng thái của tiến trình bị ngắt o Chuyển địa chỉ của chương trình xử lý ngắt vào thanh ghi con trỏ lệnh Sử dụng bảng vector ngắt (IBM-PC) o Thực hiện chương trình xử lý ngắt
• Đây là cách đơn giản nhất để thiết bị I/O giao tiếp với bộ xử lý Qúa trình kiểm tra trong một khoảng thời gian nhất định của thiết bị để xem đã đến lúc cho I/O operation tiếp theo hay chưa I/O device chỉ cần đưa thông tin vào thanh ghi trạng thái và bộ xử lí (CPU) phải đến và lấy thông tin.
• Polling là một giao thức thông báo cho CPU rằng một thiết bị cần được chú ý. Không giống như trong ngắt, nơi thiết bị nói với CPU rằng nó cần CPU xử lý, trong thăm dò CPU giữ hỏi thiết bị I/O có cần CPU xử lý hay không
• CPU liên tục kiểm tra từng thiết bị gắn với nó để phát hiện xem có thiết bị nào cần CPU chú ý hay không Mỗi thiết bị có một sẵn sàng ra lệnh bit cho biết trạng thái của thiết bị đó, tức là nó có một số lệnh được CPU thực thi hay không
• Nếu bit lệnh được đặt 1, sau đó nó có một số lệnh để được thực thi khác nếu bit 0,thì nó không có lệnh Nếu bit bận được thiết lập 1, thì nó đang bận thực hiện lệnh của một số thiết bị, còn lại thì 0.
Chuyển yêu cầu I/O thành các hoạt động phần cứng
Người dùng yêu cầu dữ liệu bằng cách sử dụng tên tệp, cuối cùng phải được ánh xạ tới các khối dữ liệu từ một thiết bị cụ thể được quản lý bởi trình điều khiển thiết bị
• Linux sử dụng bảng mount để ánh xạ các tiền tố tên tệp (ví dụ /usr) tới các thiết bị được gắn kết cụ thể Trong trường hợp nhiều mục nhập trong bảng gắn kết khớp với các tiền tố khác nhau của tên tệp thì mục nhập khớp với tiền tố dài nhất sẽ được chọn (ví dụ /usr/home thay vì /usr trong đó cả hai đều tồn tại trong bảng mount và cả hai đều khớp với tệp mong muốn)
• Linux sử dụng các tệp thiết bị đặc biệt, thường nằm trong /dev, để đại diện và truy cập trực tiếp vào các thiết bị vật lý o Mỗi tệp thiết bị có một số chính và phụ được liên kết với nó, được lưu trữ và hiển thị ở nơi kích thước tệp thường đi + Số thiết bị chính là một chỉ mục trong một bảng trình điều khiển thiết bị và cho biết trình điều khiển thiết bị nào xử lý thiết bị này (ví dụ: trình xử lý ổ đĩa)
+ Số thiết bị phụ là một tham số được chuyển cho trình điều khiển thiết bị và cho biết thiết bị cụ thể nào sẽ được truy cập, trong số nhiều thiết bị có thể được xử lý bởi trình điều khiển thiết bị cụ thể (ví dụ: một ổ đĩa hoặc phân vùng cụ thể)
Ví dụ hình dưới đây sẽ mô tả chu kỳ điển hình của một yêu cầu đọc chặn, cho thấy rằng một hoạt động I/O đòi hỏi nhiều bước cùng nhau tiêu tốn một số lượng lớn các chu kỳCPU
Figure 6: Chu kì của một yêu cầu I/O
Driver cho thiết bị USB
Driver cho bàn phím USB
Viết driver cho bàn phím USB
4.4.1 Khung chương trình struct usb_
/* Chua thong tin thiet bi */
}; static struct usb_device_id _table [ ] = {
/* Chua id cua thiet bi */ )
}; static const unsigned char _keycode [ 256] = {
/* Bang ma mo ta ban phim voi chuc nang ngat */
}; static void _irq( struct urb *urb)
/* Ham ngat duoc goi khi co phim duoc nhan */ static int _probe( struct usb_interface *intf, const struct usb_device_id *id)
/* Ham duoc goi khi thiet bi duoc ket noi voi may tinh
/* Cac ham khoi tao file luu du lieu chia se tu kernel space toi user space */ int vchar _hw_init(vchar_dev_t *hw)
/* Tao bo dem, Khoi tao gia tri thanh ghi */
} void vchar_hw_exit(vchar_dev_t *hw)
} static int dev_open(struct inode *inode, struct file *filp)
/* Cac ham chia se du lieu tu kernel space toi user space static int dev_open(struct inode *inode, struct file *filp
/*Mo device file */ static ssize_t dev_read(struct file *filp, char user *buffer, size_t len, loff_t *offset)
{ /* Copy du lieu tu kernel space toi bo dem */ copy_to_user(buffer, ¤t_data, number_byte_copy) } static int dev_release(struct inode *inode, struct file *filp)
} static static void _disconnect( struct usb_interface
/* Ham duoc goi khi thiet bi duoc rut ra khoi may tinh */
4.4.2 Các thư viện sử dụng trong chương trình
: Thư viện có các hàm với chức năng cấp phát bộ nhớ, khởi tạo.
: Sử dụng cho KERN_INFO.
: Thư viện này cung cấp các macro.
: Thư viện này có chức năng khởi tạo.
: Sử dụng cho input của các thiết bị.
: Sử dụng cho USB HID cho hệ điều hành nhận diện tất cả các id của thiết bị bàn phím usb, chuột usb gồm usb_vendor_id, usb_product_id.
: Chứa các hàm để thao tác với tệp.
: Chứa các thành phần dành riêng cho thiết bị như ngắt, cấu trúc dữ liệu, ánh xạ địa chỉ dành cho thiết bị ngoại vi.
: Chứa các định nghĩa hàm như copy_to_user, copy_from_user để truy cập địa chỉ bộ nhớ của tiến trình người dùng.
: Các ứng dụng tiện ích của giao diện thiết bị điều khiển.
4.4.3 Bảng dữ liệu điều khiển bàn phím
Bàn phím USB giao tiếp với phần mềm bằng cách gửi các báo cáo (sử dụng truyền ngắt mili giây/một lần và khoảng thời gian này được xác định trong bộ mô tả ngắt IN
} static struct usb_driver _drv = {
= _id_table static int usb__init( void)
} static void usb__exit( void)
} module_init( usb__init); module_exit( usb__exit);
DULE_LICENSE(“GPL”); của bàn phím USB).
Báo cáo bàn phím USB có thể có kích thước tối đa 8 byte, mặc dù không phải tất cả các byte này đều được sử dụng và có thể triển khai đúng cách chỉ sử dụng ba hoặc bốn byte đầu tiên.
Cấu trúc đầy đủ gồm 8 byte (1 byte + 1byte +6 byte):
Byte đầu tiên là Modifier keys status: Mỗi bit tương ứng với một khóa bổ trợ cụ thể khi một bit được nhấn cùng với phím bổ trợ tương ứng Các giá trị nằm ở trong byte đầu tiên:
Byte thứ 2 là Reserved field: Byte này được dành riêng bởi đặc tả USB HID, và do đó phần mềm sẽ bỏ qua nó.
Các byte còn lại là Keypress fields: Mỗi một phím có một mã tương ứng gọi là scan code (mã quét).
Khi một phím được nhấn xuống, bàn phím thông báo và chuyển scan code của phím đó cho máy tính.
Nếu phím đã được nhấn xuống và giữ im (không buông tay) sau một thời gian (initial delay), bàn phím sẽ tiếp tục chuyển scan code của phím đó cho máy tính theo một tốc độ xác định (repeat rate) Scan code trong trường hợp này được gọi là Pressed-key.
Khi phím được ngưng nhấn (buông tay), bàn phím chuyển scan code của phím đó cho máy tính sau khi cộng thêm 128 Scan code trong trường hợp này được gọi là Released-key.
4.4.4 Hàm thăm dò thiết bị probe
Sau khi khởi tạo thiết bị, chương trình sẽ gọi vào hàm probe. static int myusb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id)
Hàm probe này được sử dụng để thăm dò và tìm kiếm thiết bị, kiểm tra thông tin được chuyển đến nó về thiết bị và quyết định xem trình điều khiển có thực sự phù hợp với thiết bị đó hay không.
Một con trỏ tới struct usb_device_id mà USB Core được sử dụng để đưa ra quyết định này cũng được chuyển tới hàm này Nếu USB Driver xác nhận cấu trúc usb_interface được chuyển cho nó, nó sẽ khởi tạo thiết bị đúng cách và trả về 0 Nếu Driver không muốn xác nhận thiết bị hoặc xảy ra lỗi, nó sẽ trả về giá trị lỗi âm.
Khai báo con trỏ endpoint và interface
Tiếp theo, ta cần cấp phát bộ nho cho bàn phím được cắm vào Hàm dưới đây sẽ cấp phát vùng cho cho bàn phím Hàm này cần sử dụng input_free_device() để giải phóng các thiết bị chưa được đăng ký và input_unregister_device() để hủy cho các thiết bị đã đăng ký Hàm trả về input_dev hoặc trả về NULL nếu rỗng. Input_dev là struct đại diện cho thiết bị đầu vào.
Tiếp theo cần cài đặt input_dev. Đăng ký cấu trúc input_dev struct usb_device *dev = interface_to_usbdev(intf); struct usb_endpoint_descriptor *endpoint; struct usb_host_interface *interface; myusb_kbd_dev=input_allocate_device(); set_bit(EV_KEY, myusb_kbd_dev->evbit); set_bit(EV_REP, myusb_kbd_dev->evbit); for (i = 0; i < 252; i++) set_bit(usb_kbd_keycode[i], myusb_kbd_dev->keybit); clear_bit(0, myusb_kbd_dev->keybit); if(input_register_device(myusb_kbd_dev)==1){}
Hàm input_register_device để đăng kí thiết bị với tham số đầu vào. Myusb_kbd_dev là thiết bị được đăng ký Để thực hiện được hàm này thì thiết bị cần phải được cấp phát qua câu lệnh input_allocate_device và thiết lập tất cả các thành phần của thiết bị trước khi đăng ký Nếu hàm không thực hiện thành công cần được giải phóng bằng input_free_device Khi được đăng ký thành công thì khi hủy sẽ phải gọi hàm input_unregister_device.
Sau đó sẽ cài đặt tryền dữ liệu cho bàn phím.
Khởi tạo endpoint thông qua hàm usb_rcvintpipe Tại đây pipe là thông tin endpoint của usb_device mục tiêu được gửi bởi urb Giá trị sẽ phụ thuộc vào hướng truyền dữ liệu.
Tiếp theo cần cấp phát bộ đệm cho USB
Tại đây, wMaxPacketSize là độ dài tối đa của 1 gói tin được truyền từ endpoint. Hàm usb_alloc_coherent để phân bổ bộ đem DMA, chúng sẽ đồng nhất với URB_NO_xxx_DMA_MAP Hàm này có 4 tham số Tham số đầu tiên có kiểu dữ liệu usb_device là đầu vào của thiết bị đệm sẽ được sử dụng, tham số thứ 2 là kích thước của bộ đệm yêu cầu đã khai báo ở trên, tham số thứ 3 là cờ được sử dụng nếu ảnh hưởng đến việc cấp phát thì sẽ gọi cờ này, và tham số cuối cùng sẽ trả về địa chỉ cảu bộ đệm DMA.
Giá trị sẽ trả về NULL (cho biết là không có bộ đệm nào được cấp phát) hoặc nếu thành công thì con trỏ cpu-space sẽ trỏ tới bộ đệm có thể được sử dụng DMA cho thiết bị được chỉ định Các con trỏ cpu-space như vậy sẽ được trả về cùng với con trỏ địa chỉ DMA Khi giải phóng cần sử dụng hàm usb_free_coherent().
Tiếp theo cần khởi tạo cấu trúc urb thông qua usb_alloc_urb() và usb_fill_int_urb(). pipe=usb_rcvintpipe(dev,endpoint->bEndpointAddress); myusb_kbd_size=endpoint->wMaxPacketSize;myusb_kbd_buf usb_alloc_coherent(dev,myusb_kbd_size,GFP_ATOMIC,&myusb_kbd_p hyc); myusb_kbd_urb=usb_alloc_urb(0,GFP_KERNEL);
Chương trình tầng User
Qua quá trình tìm hiểu lý thuyết về quản lý thiết bị vào ra và thực hành viết diver cho bàn phím USB chúng em đã hiểu hơn về cách viết driver cho thiết bị trong Linux, bên cạnh đó hiểu về cách hoạt động, tổ chức của hệ điều hành Linux. Chúng em đã đạt được những mục tiêu đề ra:
Quản lý thiết bị vào ra, đặc biệt thiết bị ký tự trong hệ điều hành Linux.
Quy trình để viết driver cơ bản trong hệ điều hành Linux.
Viết driver cho bàn phím USB và nhấn phím “C” để chụp màn hình. Trong quá trình tìm hiểu và báo cáo không thể tránh khỏi những sai sót vì vậy chúng em mong thầy thông cảm và mong muốn nhận được những lời đóng góp quý báu của thầy để bổ sung, hoàn thiện hơn kiến thức và kỹ năng của mình.
] https://davejingtian.org/2019/07/17/usb-fuzzing-a-usb- perspective/
] http://tailieudientu.lrc.tnu.edu.vn/Chi-tiet/quy-trinh- viet-driver-cho-cac-thiet-bi-theo-chuan-usb-trong-he- thong-nhung-linux-42053.html
] https://www.keil.com/pack/doc/mw/USB/html/_u_s_b en dpoints.html