udev實現熱插拔

来源:http://www.cnblogs.com/linhaostudy/archive/2017/11/12/7820518.html
-Advertisement-
Play Games

一、UDEV是什麼? Udev是一個針對Linux內核2.6的可提供自動創建的設備節點和命名的解決方法的一個文件系統;其實與/etc/目錄下的fstab文件類似 二、Udev如何獲取內核這些模塊的變化信息? 參考博客:http://blog.chinaunix.net/uid-24943863-id ...


一、UDEV是什麼?

Udev是一個針對Linux內核2.6的可提供自動創建的設備節點和命名的解決方法的一個文件系統;其實與/etc/目錄下的fstab文件類似

 

二、Udev如何獲取內核這些模塊的變化信息?

參考博客:http://blog.chinaunix.net/uid-24943863-id-3223000.html

設備節點的創建,是通過sysfs介面分析dev文件取得設備節點號,這個很顯而易見。那麼udevd是通過什麼機制來得知內核里模塊的變化情況,如何得知設備的插入移除情況呢?當然是通過hotplug機制了,那hotplug又是怎麼實現的?或者說內核是如何通知用戶空間一個事件的發生的呢?   答案是通過netlink socket通訊,在內核和用戶空間之間傳遞信息。  

新的Linux內核使用udev代替了hotplug作為熱拔插管理,雖然有udevd管理熱拔插,但有時候我們還是需要在應用程式中檢測熱拔插事件以便快速地處理,比如在讀寫SD卡的時候拔下SD卡,那麼需要立即檢測出該情況,然後結束讀寫線程,防止VFS崩潰。Netlink是面向數據包的服務,為內核與用戶層搭建了一個高速通道,是udev實現的基礎。該工作方式是非同步的,用戶空間程式不必使用輪詢等技術來檢測熱拔插事件

 

內核中使用uevent事件通知用戶空間,uevent首先在內核中調用netlink_kernel_create()函數創建一個socket套接字,該函數原型在netlink.h有定義,其類型是表示往用戶空間發送消息的NETLINK_KOBJECT_UEVENT,groups=1,由於uevent只往用戶空間發送消息而不接受,因此其輸入回調函數input和cb_mutex都設置為NULL。

 

struct sock *netlink_kernel_create(struct net *net,int unit,unsigned int groups,                                                   void (*input)(struct sk_buff *skb),                                                   struct mutex *cb_mutex,
                                                  struct module *module); ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, 1, NULL, NULL, THIS_MODULE); 當有事件發生的時候,調用 kobject_uevent()函數,實際上最終是調用 netlink_broadcast_filtered(uevent_sock, skb , 0, 1, GFP_KERNEL , kobj_bcast_filter, kobj); 完成廣播任務。   用戶空間程式只需要創建一個socket描述符,將描述符綁定到接收地址,就可以實現熱拔插事件的監聽了。  
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <errno.h>
 5 #include <sys/types.h>
 6 #include <asm/types.h>
 7 //該頭文件需要放在netlink.h前面防止編譯出現__kernel_sa_family未定義
 8 #include <sys/socket.h>  
 9 #include <linux/netlink.h>
10 
11 void MonitorNetlinkUevent()
12 {
13     int sockfd;
14     struct sockaddr_nl sa;
15     int len;
16     char buf[4096];
17     struct iovec iov;
18     struct msghdr msg;
19     int i;
20 
21     memset(&sa,0,sizeof(sa));
22     sa.nl_family=AF_NETLINK;
23     sa.nl_groups=NETLINK_KOBJECT_UEVENT;
24     sa.nl_pid = 0;//getpid(); both is ok
25     memset(&msg,0,sizeof(msg));
26     iov.iov_base=(void *)buf;
27     iov.iov_len=sizeof(buf);
28     msg.msg_name=(void *)&sa;
29     msg.msg_namelen=sizeof(sa);
30     msg.msg_iov=&iov;
31     msg.msg_iovlen=1;
32 
33     sockfd=socket(AF_NETLINK,SOCK_RAW,NETLINK_KOBJECT_UEVENT);
34     if(sockfd==-1)
35         printf("socket creating failed:%s\n",strerror(errno));
36     if(bind(sockfd,(struct sockaddr *)&sa,sizeof(sa))==-1)
37         printf("bind error:%s\n",strerror(errno));
38 
39     len=recvmsg(sockfd,&msg,0);
40     if(len<0)
41         printf("receive error\n");
42     else if(len<32||len>sizeof(buf))
43         printf("invalid message");
44     for(i=0;i<len;i++)
45         if(*(buf+i)=='\0')
46             buf[i]='\n';
47     printf("received %d bytes\n%s\n",len,buf);
48 }
49 
50 int main(int argc,char **argv)
51 {
52     MonitorNetlinkUevent();
53     return 0;
54 }

創建socket描述符的時候指定協議族為AF_NETLINK或者PF_NETLINK,套接字type選擇SOCK_RAW或者SOCK_DGRAM,Netlink協議並不區分這兩種類型,第三個參數協議填充NETLINK_KOBJECT_UEVENT表示接收內核uevent信息。接著就綁定該文件描述符到sockadd_nl,註意該結構體nl_groups是接收掩碼,取~0是將接收所有來自內核的消息,我們接收熱拔插只需要NETLINK_KOBJECT_UEVENT即可。接下來調用recvmsg開始接收內核消息,recvmsg函數需要我們填充message報頭,包括指定接收緩存等工作。該函數會阻塞直到有熱拔插事件產生。

    運行程式,然後我插入一個U盤,得到下麵的結果: $ ./netlink  received 289 bytes add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1 ACTION=add DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1 SUBSYSTEM=usb MAJOR=189 MINOR=8 DEVNAME=bus/usb/001/009 DEVTYPE=usb_device DEVICE=/proc/bus/usb/001/009 PRODUCT=781/5530/100 TYPE=0/0/0 BUSNUM=001 DEVNUM=009 SEQNUM=2306   運行程式,拔掉U盤 $ ./netlink  received 294 bytes remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0/host10/target10:0:0/10:0:0:0/bsg/10:0:0:0 ACTION=remove DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0/host10/target10:0:0/10:0:0:0/bsg/10:0:0:0 SUBSYSTEM=bsg MAJOR=253 MINOR=2 DEVNAME=bsg/10:0:0:0 SEQNUM=2345   程式正確地接收到了U盤熱拔插事件,通過該信息用戶程式可以在第一時間得到事件通知。事實上熱拔插的時候產生的消息可不止一條呢,可以在revmsg的時候用一個迴圈接收更多的消息。  
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 今天是雙十一這個青年人同慶的日子,一年一度的剁手節又開始了,我相信正在逛著淘寶網站的同志們一定被彈出的廣告搞得不厭其煩吧...那麼,網站的廣告是怎麼使用腳本寫出來的呢? 下麵就讓我們簡單地介紹一下網站彈出廣告的這個效果吧。 一、案例介紹 首先我們想要在網站的頂部做一個能夠定時彈出廣告的東西,效 ...
  • 這是我自己早前聽課時整理的前端全套知識點,適用於初學者,也可以適用於中級的程式員,你們可以下載下來。我自認為還是比較系統全面的,可以抵得上市場上90%的學習資料。討厭那些隨便亂寫的資料還有拿出來賣錢的人!在這裡我免費的分享出來供大家使用! 在這個平臺真的可以學習到不少的東西!有很多的人都在無私的奉獻 ...
  • 關註微信公眾號《IT技術資源共用》獲取更多資源! 微信號:feng1376311650 或者掃二維碼關註獲取下麵全部資源: python: 【0001】Python安裝包,教程文檔,工具包 鏈接: http://pan.baidu.com/s/1hsnHizM 密碼:9x03 【0002】Pytho ...
  • E-R模型(實體關係模型) 當前物理的資料庫都是按照E-R模型進行設計的 E表示entry,實體 R表示relationship,關係 一個實體轉換為資料庫中的一個表 關係描述兩個實體之間的對應規則,包括 一對一 一對多 多對多 關係轉換為資料庫表中的一個列 *在關係型資料庫中一行就是一個對象 數據... ...
  • create table test( id int(10) unsigned not null auto_increment, name varchar(10) character set utf8, age int(10),primary key(id)) engine=MyISAM create ...
  • DBLINK資料庫鏈接是一個資料庫中的模式對象,使您可以訪問另一個資料庫上的對象。 dblink限定符允許您引用除本地資料庫以外的資料庫中的對象,如果省略了dblink,那麼Oracle假定您指的是本地資料庫中的一個對象,並非所有的SQL語句都允許您訪問遠程資料庫上的對象。 新增: 方法一:藉助配置 ...
  • 1、找到redis.conf,配置密碼 2、要重新啟動一下redis 3、用redis-cli重新登陸,我們查詢的時候提示“Authentication required”查詢失敗 4、重新帶密碼登陸,發現可以查詢了 參考: [1]博客,http://blog.csdn.net/zyz5119197 ...
  • 概述 MongoDB是目前非常流行的一種非關係型資料庫,作為入門系列的第一篇本篇文章主要介紹Mongdb的基礎概念知識包括命名規則、數據類型、功能以及安裝等。 環境: OS:Windows Version:3.4 一、安裝 1.下載解壓 在官網下載對應操作系統版本的安裝包,然後解壓;我這裡使用Win ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...