生活随笔
收集整理的這篇文章主要介紹了
Linux下自动检测USB热插拔
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
做嵌入式開發(fā),尤其在網關、路由器或者其他支持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內置功能,所以使用起來很簡單:創(chuàng)建一個AF_NETLINK協議族下NETLINK_KOBJECT_UEVENT類型的特殊文件描述符(套結字)CppLive,然后利用setsocketopt允許該文件描述符(套結字)復用其他端口,再利用band函數將自身進程綁定到特殊文件描述符(套結字)CppLive,最后利用select在while循環(huán)內監(jiān)聽CppLive是否可讀,如果可讀則調用recv接收Linux系統(tǒng)內核傳遞過來的數據并打印出來,這些輸出便是USB熱插拔信息。當然你也可以個性化地處理來自內核的熱插拔信息,讓程序變得更加智能以及人性化。
利用NETLINK檢測USB熱插拔的C語言實現代碼如下:
view plaincopy to clipboardprint?
#include?<stdio.h>?? #include?<stdlib.h>?? #include?<string.h>?? #include?<fcntl.h>?? #include?<sys/socket.h>?? #include?<linux/netlink.h>?? #define?UEVENT_BUFFER_SIZE?2048?? ?? int?main(void)?? {?? ????struct?sockaddr_nl?client;?? ????struct?timeval?tv;?? ????int?CppLive,?rcvlen,?ret;?? ????fd_set?fds;?? ????int?buffersize?=?1024;?? ????CppLive?=?socket(AF_NETLINK,?SOCK_RAW,?NETLINK_KOBJECT_UEVENT);?? ????memset(&client,?0,?sizeof(client));?? ????client.nl_family?=?AF_NETLINK;?? ????client.nl_pid?=?getpid();?? ????client.nl_groups?=?1;??? ????setsockopt(CppLive,?SOL_SOCKET,?SO_RCVBUF,?&buffersize,?sizeof(buffersize));?? ????bind(CppLive,?(struct?sockaddr*)&client,?sizeof(client));?? ????while?(1)?{?? ????????char?buf[UEVENT_BUFFER_SIZE]?=?{?0?};?? ????????FD_ZERO(&fds);?? ????????FD_SET(CppLive,?&fds);?? ????????tv.tv_sec?=?0;?? ????????tv.tv_usec?=?100?*?1000;?? ????????ret?=?select(CppLive?+?1,?&fds,?NULL,?NULL,?&tv);?? ????????if(ret?<?0)?? ????????????continue;?? ????????if(!(ret?>?0?&&?FD_ISSET(CppLive,?&fds)))?? ????????????continue;?? ?????????? ????????rcvlen?=?recv(CppLive,?&buf,?sizeof(buf),?0);?? ????????if?(rcvlen?>?0)?{?? ????????????printf("%s\n",?buf);?? ?????????????? ????????}?? ????}?? ????close(CppLive);?? ????return?0;?? }??
運行程序,測試U盤插入/拔除,輸出如下:
view plaincopy to clipboardprint?
add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1?? add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0?? add@/module/usb_storage?? add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6?? add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/scsi_host/host6?? add@/bus/usb/drivers/usb-storage?? add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0?? add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0?? add@/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?? add@/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?? add@/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?? add@/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?? change@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0?? add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb?? add@/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?? add@/devices/virtual/bdi/8:16?? add@/module/fat?? add@/kernel/slab/fat_cache?? add@/kernel/slab/fat_inode_cache?? add@/module/vfat?? add@/module/nls_cp437?? add@/module/nls_iso8859_1?? remove@/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?? remove@/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?? remove@/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?? remove@/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?? remove@/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?? remove@/devices/virtual/bdi/8:16?? remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb?? remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0?? remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/scsi_host/host6?? remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6?? remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0?? remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1?? remove@/host6/target6:0:0 ?
轉自http://www.cpplive.com/html/1355.html
總結
以上是生活随笔為你收集整理的Linux下自动检测USB热插拔的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。