udev 事件处理

来源:互联网 发布:程序员竖屏显示器 编辑:程序博客网 时间:2024/06/08 17:55

 处理 hotplug 传统的方法是,在内核中执行一个称为 hotplug 的程序,相关参数通过环境变量传递过来,再由 hotplug 通知其它关注 hotplug 事件的应用程序。这样做不但效率低下,而且感觉也不那么优雅。新的方法是采用 NETLINK 实现的,这是一种特殊类型的 socket ,专门用于内核空间与用户空间的异步通信。下面的这个简单的例子,可以监听来自内核 hotplug 的事件。

 

#include < stdio .h>

#include <stdlib.h>

#include < string .h>

#include < ctype .h>

#include <sys/un.h>

#include <sys/ioctl.h>

#include <sys/ socket .h>

#include <linux/types.h>

#include <linux/netlink.h>

#include < errno .h>

 

static int init_hotplug_sock ( void )

{

    struct sockaddr_nl snl ;

    const int buffersize = 16 * 1024 * 1024;

    int retval ;

 

    memset (& snl , 0x00, sizeof ( struct sockaddr_nl));

    snl .nl_family = AF_NETLINK;

    snl .nl_pid = getpid ();

    snl .nl_groups = 1;

 

    int hotplug_sock = socket (PF_NETLINK, SOCK_DGRAM , NETLINK_KOBJECT_UEVENT);

    if ( hotplug_sock == -1) {

        printf ( "error getting socket: %s" , strerror ( errno ));

        return -1;

    }

 

    /* set receive buffersize */

    setsockopt ( hotplug_sock , SOL_SOCKET , SO_RCVBUFFORCE, & buffersize , sizeof ( buffersize ));

 

    retval = bind ( hotplug_sock , ( struct sockaddr *) & snl , sizeof ( struct sockaddr_nl));

    if ( retval < 0) {

        printf ( "bind failed: %s" , strerror ( errno ));

        close ( hotplug_sock );

        hotplug_sock = -1;

        return -1;

    }

 

    return hotplug_sock ;

}

 

#define UEVENT_BUFFER_SIZE       2048

 

int main ( int argc , char * argv [])

{

         int hotplug_sock        = init_hotplug_sock ();

 

         while (1)

         {

                   char buf [ UEVENT_BUFFER_SIZE *2] = {0};

                   recv ( hotplug_sock , & buf , sizeof ( buf ), 0); 

                   printf ( "%s/n" , buf );

         }

 

         return 0;

}

 

编译:

gcc -g hotplug.c -o hotplug_monitor

 

运行后插 / 拔 U 盘,可以看到:

add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1

add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/usbdev2.2_ep00

add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0

add@/class/scsi_host/host2

add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep81

add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep02

add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep83

add@/class/usb_device/usbdev2.2

add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host2/target2:0:0/2:0:0:0

add@/class/scsi_disk/2:0:0:0

add@/block/sda

add@/block/sda/sda1

add@/class/scsi_device/2:0:0:0

add@/class/scsi_generic/sg0

remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep81

remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep02

remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep83

remove@/class/scsi_generic/sg0

remove@/class/scsi_device/2:0:0:0

remove@/class/scsi_disk/2:0:0:0

remove@/block/sda/sda1

remove@/block/sda

remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host2/target2:0:0/2:0:0:0

remove@/class/scsi_host/host2

remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0

remove@/class/usb_device/usbdev2.2

remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/usbdev2.2_ep00

remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1