首頁  >  文章  >  系統教程  >  Linux怎麼辨識到我插入的裝置USB裝置是什麼裝置的呢?

Linux怎麼辨識到我插入的裝置USB裝置是什麼裝置的呢?

PHPz
PHPz轉載
2024-02-09 14:15:15902瀏覽

一、前言

#在學習Linux作業系統時,你是否曾經有過這樣的疑問:為什麼我們的電腦能夠辨識並使用不同的USB設備呢?為什麼Linux系統不會把滑鼠當成鍵盤來使用呢?讓我們一起來探討一下USB設備在Linux系統中的辨識和載入過程。

二、USB設備的辨識與載入

當我們將一個USB裝置插入電腦時,Linux核心會自動偵測並載入對應的驅動程序,使裝置能夠正常運作。接下來,我們將深入探討USB設備在Linux系統中的辨識與載入過程。

Linux怎麼辨識到我插入的裝置USB裝置是什麼裝置的呢?

2.1 USB控制器偵測裝置插入

#USB控制器是一個硬體設備,用於控制USB匯流排上的設備。當你插入一個USB設備時,USB控制器會偵測到電壓變化並發出中斷訊號。這個中斷訊號被送到處理器上的USB控制器中斷線上,告訴Linux核心有新的USB設備插入。

2.2 核心偵測並載入驅動程式

當核心接收到USB控制器發出的中斷訊號時,它會呼叫USB子系統中的usbcore模組,該模組負責偵測新的USB裝置並載入對應的驅動程式。 usbcore模組首先會偵測設備的描述符,這個描述符包含設備的廠商ID、產品ID、類別碼等資訊。

如果已經存在一個符合的驅動程序,那麼usbcore模組就會載入這個驅動程式。如果沒有匹配的驅動程序,則會嘗試載入一個通用的驅動程序,這個驅動程式能夠支援大多數USB裝置。

2.3 驅動程式向USB子系統註冊

#一旦正確的驅動程式被加載,它會向USB子系統註冊並告訴它自己可以處理哪些設備。這一步驟通常包括向內核註冊USB設備的類別(如儲存設備、輸入設備等)。

這個過程包括了向核心註冊一個新的USB裝置驅動程序,並在該驅動程式中指定裝置的廠商ID、產品ID等資訊。一旦驅動程式被成功註冊,USB子系統就可以將裝置與正確的驅動程式進行配對。

2.4 USB子系統建立裝置節點

USB子系統接下來會為設備建立一個設備節點。設備節點是一個特殊的文件,在/dev目錄下,它允許用戶空間程式與設備通訊。設備節點的名稱通常是由核心根據設備的廠商ID、產品ID和序號等資訊動態產生的。

裝置節點的建立是透過udev守護程式實現的,這個守護程式會監視系統中的裝置插拔事件,並自動建立或刪除對應的裝置節點。建立設備節點之後,核心就可以將設備的存取權限指派給使用者空間程式。

2.5 驅動程式初始化裝置

驅動程式被通知有新的裝置插入後,它會對裝置進行初始化。初始化可能包括設定裝置的傳輸速率、分配記憶體緩衝區等。設備初始化完成後,驅動程式會向USB子系統報告設備已準備好。

2.6 使用者空間程式開啟裝置:

最後,使用者空間程式可以開啟設備節點並與設備通訊。設備節點的權限通常被設定為只允許root使用者或在相關群組中的使用者存取。使用者空間程式可以使用系統呼叫(如readwrite)向裝置發送命令和接收資料。

透過這個過程,Linux系統可以自動識別設備並載入相應的驅動程序,使設備可以正常工作。這也是為什麼當我們插入USB設備時,我們不需要手動安裝任何驅動程式或執行任何其他操作就可以直接開始使用設備。

當你插入一個USB設備時,Linux系統會自動執行上述步驟,從而自動識別設備並加載相應的驅動程序,使設備可以正常工作。下面我們從程式碼的層次來分析一下這個過程。

三、程式碼實作講解

下面我透過一些範例程式碼,講解一下USB設備在Linux系統中的辨識和載入過程。這些範例程式碼只是講解一下原理,實際程式碼將會更加複雜。

3.1 偵測裝置插入

當USB設備插入到系統中時,會產生一個中斷訊號,這個訊號會被處理器上的USB控制器中斷線捕獲,並由核心的USB子系統處理。以下是範例程式碼,示範如何偵測USB設備的插入和拔出事件:

#include 
#include 

int main() {
    libusb_device **devs;
    libusb_context *ctx = NULL;

    int r = libusb_init(&ctx);
    if (r printf("Failed to initialize libusb\n");
        return 1;
    }

    // 扫描USB总线并列出所有连接的设备
    ssize_t cnt = libusb_get_device_list(ctx, &devs);
    if (cnt printf("Failed to get device list\n");
        return 1;
    }

    // 遍历设备列表,检测插入和拔出事件
    for (int i = 0; i if (r printf("Failed to get device descriptor\n");
            continue;
        }

        printf("Vendor ID: 0x%04x, Product ID: 0x%04x\n", desc.idVendor, desc.idProduct);
    }

    // 释放设备列表
    libusb_free_device_list(devs, 1);

    // 退出libusb
    libusb_exit(ctx);

    return 0;
}

這段程式碼使用了libusb函式庫,這是一個C語言函式庫,用來存取USB裝置。它提供了一個用於初始化USB子系統和掃描USB匯流排的API,以及用於存取USB設備的API。

3.2 載入驅動程式

一旦偵測到裝置插入,USB子系統會嘗試載入一個適當的驅動程式。下面是一個範例驅動程式程式碼,它負責支援USB儲存裝置(例如USB線):

#include 
#include 

static struct usb_device_id storage_devices[] = {
    { USB_DEVICE(0xabcd, 0x1234) },
    { USB_DEVICE(0xffff, 0xffff) },
    { }
};
MODULE_DEVICE_TABLE(usb, storage_devices);

static int storage_probe(struct usb_interface *interface, const struct usb_device_id *id) {
    // 初始化设备并注册
    return 0;
}

static void storage_disconnect(struct usb_interface *interface) {
    // 释放设备
}

static struct usb_driver storage_driver = {
    .name = "usb-storage",
    .probe = storage_probe,
    .disconnect = storage_disconnect,
    .id_table = storage_devices,
};

module_usb_driver(storage_driver);

這段程式碼示範了一個簡單的驅動程序,它可以處理USB儲存裝置的插入和拔出事件。在載入驅動程式時,核心將搜尋已載入的驅動程式列表,以尋找與裝置相符的驅動程式。

如果找到了匹配的驅動程序,核心將使用該驅動程式來管理該裝置。如果沒有找到匹配的驅動程序,核心將不會載入任何驅動程式。

3.3 裝置註冊

一旦找到了與裝置相符的驅動程序,驅動程式將被載入並啟動,它將嘗試對裝置進行初始化,並將其註冊到核心。下面是一個範例程式碼,示範如何初始化USB儲存裝置並將其註冊到核心:

static int storage_probe(struct usb_interface *interface, const struct usb_device_id *id) {
    struct usb_device *dev = interface_to_usbdev(interface);

    // 获取设备描述符
    struct usb_device_descriptor desc;
    int r = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &desc, sizeof(desc));
    if (r "Failed to get device descriptor\n");
        return r;
    }

    // 打印设备信息
    printk(KERN_INFO "USB storage device detected: Vendor ID=0x%04x, Product ID=0x%04x\n", desc.idVendor, desc.idProduct);

    // 初始化设备并注册到内核
    // ...

    return 0;
}

上面這段範例程式碼使用了核心的usb_get_descriptor()函數來取得裝置描述符,並使用printk()函數將裝置資訊記錄到核心日誌中。

當驅動程式將呼叫設備初始化函數並將其註冊到內核,但是由於設備初始化和註冊的過程因設備而異,因此這裡省略了這部分程式碼。

3.4 设备访问

一旦设备已经被注册到内核,用户空间程序就可以通过设备节点来访问设备。在Linux系统中,设备节点是一种特殊的文件,可以通过标准文件I/O函数来访问。下面是一个示例代码,演示如何打开并读取USB存储设备:

#include 
#include 
#include 

int main() {
    // 打开设备节点
    int fd = open("/dev/sdb", O_RDONLY);
    if (fd printf("Failed to open device\n");
        return 1;
    }

    // 读取设备数据
    char buf[1024];
    ssize_t n = read(fd, buf, sizeof(buf));
    if (n printf("Failed to read device\n");
        close(fd);
        return 1;
    }

    // 关闭设备节点
    close(fd);

    return 0;
}

这段代码使用了标准的文件I/O函数来访问设备节点。在这个例子中,设备节点的路径是/dev/sdb,这是一个典型的USB存储设备节点。接下来,程序将设备节点作为文件打开,并使用read()函数从设备中读取数据。一旦完成数据的读取,程序将关闭设备节点并退出。

四、结语

Linux系统识别USB设备的过程可以分为四个步骤:设备连接、驱动匹配、设备注册和设备访问。当用户将USB设备插入计算机时,内核将通过USB总线来检测设备的插入事件,并尝试查找与设备匹配的驱动程序。一旦找到了匹配的驱动程序,驱动程序将被加载并启动,它将尝试对设备进行初始化,并将其注册到内核。一旦设备已经被注册到内核,用户空间程序就可以通过设备节点来访问设备。

在Linux系统中,驱动程序是非常重要的组成部分,它们负责管理和控制系统中的各种设备。对于USB设备而言,内核提供了一个通用的USB驱动框架,它可以自动检测和加载驱动程序,并为用户提供了一个简单而强大的USB设备访问接口。通过深入理解USB驱动程序的工作原理,我们可以更好地理解Linux系统中设备管理的内部机制,这对于开发和调试设备驱动程序非常有帮助。

以上是Linux怎麼辨識到我插入的裝置USB裝置是什麼裝置的呢?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:lxlinux.net。如有侵權,請聯絡admin@php.cn刪除