Linux下侦测 USB Disk 插拔

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/netlink.h>


// netlink.h 中定义
//struct sockaddr_nl
//{
// sa_family_t     nl_family;   // AF_NETLINK
// unsigned short nl_pad;      // zero
// __u32       nl_pid;       // 进程ID
//    __u32       nl_groups; // 多播组掩码
//};
//


static int
monitoring_usb_device( void )
{
    // 本函数返回值
    int iResult = 0;
    // 接收内核发来的消息字符串
    char caKernelMsgBuff[1024];
    // 接收内核发来的消息缓冲区大小
    const unsigned int uiRecvBuffSize = sizeof( caKernelMsgBuff );
    // 套接字地址
    struct sockaddr_nl snl;
    // 套接字文件描述符
    int sfd = -1;


    do // 非循环,只是为了减少分支嵌套
    {
        // 1.添写套接字地址
        snl.nl_family = AF_NETLINK;
        snl.nl_pad = 0;
        // 如果希望内核处理消息或多播消息,就把该字段设置为 0,
        // 否则设置为处理消息的进程ID。
        snl.nl_pid = getpid();
        snl.nl_groups = 1;


        // 2.创建套接字
        // NETLINK_KOBJECT_UEVENT - 内核消息到用户空间,出现在 Linux 2.6.10
        sfd = socket( PF_NETLINK, // 使用 netlink
                      SOCK_DGRAM, // 使用不连续不可信赖的数据包连接
                      NETLINK_KOBJECT_UEVENT );
        // 如果 创建套接字失败 的话,则
        if ( -1 == sfd )
        {
            iResult = -1;
            break;
        }


        // 3.设置套接字接收缓冲区大小
        setsockopt( sfd,
                    SOL_SOCKET, // 存取 socket 层
                    SO_RCVBUF,  // 设置接收缓冲区大小
                    &uiRecvBuffSize,
                    sizeof( uiRecvBuffSize ) );


        // 4.将套接字加入指定的多播组
        iResult = bind( sfd,
                        (struct sockaddr*)&snl,
                        sizeof( snl ) );
        // 如果 将套接字加入指定的多播组失败 的话,则
        if ( -1 == iResult )
        {
            return -2;
            break;
        }


        while( 1 )
        {
            // 接收内核消息
            recv( sfd,
                  &caKernelMsgBuff,
                  sizeof( caKernelMsgBuff ),
                  0 );


            printf( "Kernel Message:\n%s\n", caKernelMsgBuff );


            // USB 设备的插入时,会出现以 add@/devices/ 开头,含 usb 的字符串
            if( 0 == memcmp( caKernelMsgBuff,
                             "add@",
                             4 )
                &&
                NULL != strstr( caKernelMsgBuff,
                                "usb" ) )
            {
                printf( "Add USB Device\n" );
                break;
            }


            // USB 设备的拔除时,会出现以 remove@/devices/ 开头,含 usb 的字符串
            if( 0 == memcmp( caKernelMsgBuff,
                             "remove@",
                             7 )
                &&
                NULL != strstr( caKernelMsgBuff,
                                "usb" ) )
            {
                printf( "Remove USB Device\n" );
                break;
            }
        }


        // 等一秒钟,让设备加载完毕
        sleep(1);


    }while( 0 );


    // 如果 创建套接字成功 的话,则
    if ( -1 != sfd )
    {
        // 关闭套接字
        close( sfd );
        sfd = -1;
    }


    return iResult;
}


int main(int argc, char* argv[])
{
    printf( "monitoring_usb_device return %d\n",
            monitoring_usb_device() );


    return 0;
 
}

相关推荐