初的Linux内核使用udev代替了hotplug作为热拔插管理。新的Linux内核使用udev代替了hotplug作为热拔插管理。

一、UDEV是什么?

Udev是一个针对Linux内核2.6之只是资自动创建的设备节点和命名的缓解办法的一个文件系统;其实与/etc/目录下的fstab文件类

 

一、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的时光用一个巡回接收更多之信息。

 

二、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的时刻用一个巡回接收更多之音信。

 

相关文章

网站地图xml地图