1. 程式人生 > >Linux下自動檢測USB熱插拔

Linux下自動檢測USB熱插拔

嵌入式開發,尤其在閘道器路由器或者其他支援USB裝置的終端上,為了提高使用者體驗,我們常常需要支援自動識別並掛載USB裝置功能。某些應用程式,在使用USB裝置的過程中,也希望能夠偵測到USB斷開事件,不至於某些工作因為USB已經不存在而白做。在Linux下,我們主要有兩種辦法檢測USB熱插拔。    

第一種便是定時檢查/proc/scsi/scsi檔案,該檔案內會按照標準格式儲存著當前裝置內掛載的儲存介質基本資訊,如果在PC端,除了硬碟(ATA)、光碟機(CD-ROM)外,就是USB裝置(Direct-Access)了,輪詢該scsi檔案,檢查檔案內是否新增或減少資料便可實現自動偵測USB熱插拔的效果。但是這種方法對於熱插拔(hotplug)裝置,如U盤,效果就沒那麼理想了,因為我們不知道裝置什麼時候插上,又是什麼時候被拔掉了,只能驗證當前是否已經插上或者已經拔除的事實。於是便有了另一種辦法,我們採用一種特殊類的的

檔案描述符套結字)專門用於Linux核心跟使用者空間之間的非同步通訊,這種技術通常被成為NETLINK。

由於NETLINK是Linux內建功能,所以使用起來很簡單:建立一個AF_NETLINK協議族下NETLINK_KOBJECT_UEVENT型別的特殊檔案描述符(套結字)CppLive,然後利用setsocketopt允許該檔案描述符(套結字)複用其他埠,再利用band函式將自身程序繫結到特殊檔案描述符(套結字)CppLive,最後利用select在while迴圈內監聽CppLive是否可讀,如果可讀則呼叫recv接收Linux系統核心傳遞過來的資料並打印出來,這些輸出便是USB熱插拔資訊。當然你也可以個性化地處理來自核心的熱插拔資訊,讓程式變得更加智慧以及人性化。

利用NETLINK檢測USB熱插拔的C語言實現程式碼如下:

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <fcntl.h>  
  5. #include <sys/socket.h>  
  6. #include <linux/netlink.h>  
  7. #define UEVENT_BUFFER_SIZE 2048  
  8. int main(void)  
  9. {  
  10.     struct sockaddr_nl client;  
  11.     struct
     timeval tv;  
  12.     int CppLive, rcvlen, ret;  
  13.     fd_set fds;  
  14.     int buffersize = 1024;  
  15.     CppLive = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);  
  16.     memset(&client, 0, sizeof(client));  
  17.     client.nl_family = AF_NETLINK;  
  18.     client.nl_pid = getpid();  
  19.     client.nl_groups = 1; /* receive broadcast message*/  
  20.     setsockopt(CppLive, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));  
  21.     bind(CppLive, (struct sockaddr*)&client, sizeof(client));  
  22.     while (1) {  
  23.         char buf[UEVENT_BUFFER_SIZE] = { 0 };  
  24.         FD_ZERO(&fds);  
  25.         FD_SET(CppLive, &fds);  
  26.         tv.tv_sec = 0;  
  27.         tv.tv_usec = 100 * 1000;  
  28.         ret = select(CppLive + 1, &fds, NULL, NULL, &tv);  
  29.         if(ret < 0)  
  30.             continue;  
  31.         if(!(ret > 0 && FD_ISSET(CppLive, &fds)))  
  32.             continue;  
  33.         /* receive data */  
  34.         rcvlen = recv(CppLive, &buf, sizeof(buf), 0);  
  35.         if (rcvlen > 0) {  
  36.             printf("%s\n", buf);  
  37.             /*You can do something here to make the program more perfect!!!*/  
  38.         }  
  39.     }  
  40.     close(CppLive);  
  41.     return 0;  
  42. }  

執行程式,測試U盤插入/拔除,輸出如下:

  1. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1  
  2. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0  
  3. [email protected]/module/usb_storage  
  4. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6  
  5. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/scsi_host/host6  
  6. [email protected]/bus/usb/drivers/usb-storage  
  7. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0  
  8. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0  
  9. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0  
  10. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0  
  11. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2  
  12. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0  
  13. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0  
  14. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb  
  15. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb4  
  16. [email protected]/devices/virtual/bdi/8:16  
  17. [email protected]/module/fat  
  18. [email protected]/kernel/slab/fat_cache  
  19. [email protected]/kernel/slab/fat_inode_cache  
  20. [email protected]/module/vfat  
  21. [email protected]/module/nls_cp437  
  22. [email protected]/module/nls_iso8859_1  
  23. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0  
  24. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2  
  25. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0  
  26. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0  
  27. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb4  
  28. [email protected]/devices/virtual/bdi/8:16  
  29. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb  
  30. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0  
  31. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/scsi_host/host6  
  32. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6  
  33. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0  
  34. [email protected]/devices/pci0000:00/0000:00:1d.7/usb2/2-1  
  35. [email protected]/host6/target6:0:0  


    轉自http://www.cpplive.com/html/1355.html

相關推薦

Linux自動檢測USB

做嵌入式開發,尤其在閘道器、路由器或者其他支援USB裝置的終端上,為了提高使用者體驗,我們常常需要支援自動識別並掛載USB裝置功能。某些應用程式,在使用USB裝置的過程中,也希望能夠偵測到USB斷開事件,不至於某些工作因為USB已經不存在而白做。在Linux下,我們主要有

qt linux自動檢測U盤

如果用U盤來更新軟體,需要先刪除當前的可執行檔案,但是如果刪除之後,複製失敗的話會導致後續沒有檔案可以運行了。一個方法是將新的可執行檔案放到另一個目錄中,當copy成功後修改linux的啟動檔案,然後reboot.    使用qt自帶的QDBus可以實現。 D-B

【玩轉開源】Linux C 檢測網口

int NetDetect(char *net_name, int *statue) { int ret = 0; int skfd = 0; struct ifreq ifr; skfd = socket(AF_INET, SOCK_DGRAM, 0); //建議s

linux c檢測網線(netlink)

#include <sys/types.h> #include <sys/socket.h> #include <asm/types.h> #include <linux/netlink.h> #include

linux自動檢測mongodb 有問題就重啟

import os import time import datetime output = os.popen("service mongod status").read() print( time.strftime( '%Y-%m-%d %H:%M:%S', time.l

Linux實現USB口的事件觸發

目前要做一個在嵌入式平臺上的USB口的熱插拔事件。 經過我現在的分析總結目前有如下方法: 1,定時檢查/proc/scsi/scsi檔案 此方法只能在PC上,但在嵌入式平臺上不可用。 2,netlink方式 使用netlink. #include <s

linux app應用如何檢測USB裝置

框架是這樣的。原理就是建立一個socket捕獲核心發過來的netlink訊息,很簡單的。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <

C# Winform一個的MIS/MRP/ERP框架14(自動更新)

對於軟體來說,啟用自動更新是非常必要的。 根據軟體的應用場景,我們可以設計不同的更新模型。 目前,IMES框架執行在.Net framework 4.0下面,使用的Win系統版本在Win7,域內管控,平時業務調整也不是很頻繁。 所以,我的更新很粗放,就是刪除舊檔案,拷貝新檔案: 1、更新檔案放置在檔案

Linux USB 驅動開發(四)—— 那點事

Linux USB 驅動開發(四)—— 熱插拔那點事         學習USB熱插拔之前,先學習一些USB的硬體知識: 一、USB基礎概念 1、硬體知識(USB插座和插頭)        在最初的標

MFC學習筆記 — VC++中自動檢測串列埠事件

文章出處:(轉載文章,如有不妥,通知後我會立即刪除) 文章索引1 文章索引2 這裡主要利用Cwnd的ON_WM_DEVICECHANGE訊息來處理。 Windows作業系統傳送WM_DEVICECHANGE有些限制: 1、只有頂層窗體的程式才能收到這個訊息; 2、

USB轉串列埠檢測

         上位機與裝置進行串列埠通訊之前都需要指定PC通訊的串列埠號,這無疑給操作上帶來不便,更痛苦的是每次都得到裝置管理器檢視當前連線的串列埠。          那麼如何通過程式碼獲取當前可用串列埠列表?一是通種登錄檔獲取,操作比較複雜;微軟為我們提供更簡單

C# Winform一個的MIS/MRP/ERP框架(多語言方案)

文件加載 全局 查詢 分享 技術 變量 支持 對象 style 個別時候,我們需要一種多語種切換方案。   我的想方案是這樣的: 1、使用文本文本存儲多語言元素,應用程序啟動時加載到內存表中; 2、應用程序啟動時從配置文件加載語種定義; 3、所有窗體繼承自一個Base

C# Winform一個的MIS/MRP/ERP框架11(啟航)

aer tab chan byname 可能 清理 contex cati break   初學時,有了想法卻完全不知道該從何下指,此序列將拋磚引玉,與大家共同學習進步。   一個程序的初始,必然是啟動。   我的要求:   1、應用程序保持單例;   2、從配置文件加載一

C# Winform一個的MIS/MRP/ERP框架15(窗體基類場景1)

分享 需求 權限 檢測 表名 check 系統 ref 代碼 最基礎的窗體基類其實是通過應用場景反推的結構。 以下是場景一:   單表應用,普通的數據,比如單位/顏色/特殊字典等使用者少的,無需過多控制的可以使用一個數據表格來管理。   和Excel表格差不多,批量修改,統

C# Winform一個的MIS/MRP/ERP框架16(窗體基類場景2)

基礎資料 簡單 bubuko 圖片 主鍵 筆記 沒有 窗體 熱插拔 如果沒有特別需求,和場景1一樣只變更表名,主鍵字段,檢測字段等名稱,不需要寫其它代碼了。 * 清單列表+單筆編輯/保存,適用於大多數基礎資料管理以及簡單的單據資料錄入(當然,排版是要改一改的): *

HDMI/DVI 顯示器檢測原理(HPD)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C# Winform一個的MIS/MRP/ERP框架13(窗體基類)

作為一個ERP資料處理框架,大部分的開發場景都差不多。 理想中,對於通用資料處理,我的步驟如下: 1、為窗體指定資料來源(資料表/查詢等); 2、拖入編輯控制元件,指定繫結欄位; 3、結束。 為此,我設計了幾個基類窗體,給它們分成幾個場景(如無資料/單表資料/主從表/多表關聯等),在不同的業務模型下

關於windows檢測的個人理解(使用Qt開發)

在Qt中每一個視窗類(widget)都有一個處理windows訊息的函式,當windows出現熱插拔事件的時候,會向每個視窗傳送相應的WM_訊息,在Qt下,最終將調到natevieEvent函式;下面以QWidget為例: virtual bool QWidget::nat

C# Winform一個的MIS/MRP/ERP框架(簡介)

  Programmer普弱哥們都喜歡玩自己的框架,我也不例外。   理想中,這個框架要易於理解、易於擴充套件、易於維護;最重要的,易於CODING。   系統是1主體框架+N模組的多個EXE/DLL組成的,在主體框架開啟的時候,編譯完模組EXE可以馬上響應需求,不用退系統,不用重登入。   大概的目標:來一

C# Winform一個的MIS/MRP/ERP框架(通用控制元件)

一直對商業控制元件不感冒, 結合日常工作, 我寫了幾個常用控制元件. 一、下拉框控制元件(仿Access下拉框:F4下拉,自動輸入,支援單/多列顯示),可在Datagridview中使用。 1、常規: 2、Datagridview:  二、帶按鈕的文字框(可在Datagridview中使用): 1、常