#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;
}