检测usb口HotPlug-netlink

时间:2024-03-23 21:30:41

为了完成内核空间与用户空间通信,Linux提供了基于Socket的NetLink通信机制。

SELinux,Linux系统的防火墙分为内核态的netfilter和用户态的iptables,netfilter与iptables的数据交换就是通过Netlink机制完成。
 

下面看一个检测usb口的例子:

s32 InitUsbHotPlug(void)
{
	s32 nSockFd = 0;

	// 套接字地址
	struct sockaddr_nl snl;
	bzero(&snl, sizeof(struct sockaddr_nl));
	
	// 1.添写套接字地址
	snl.nl_family = AF_NETLINK;
	snl.nl_pad = 0;
	// 设置为处理消息的进程ID。
	snl.nl_pid = getpid();
	snl.nl_groups = 1;
	
	// 2.创建套接字, 返回套接字文件描述符
	// PF_NETLINK - 使用 netlink
	// SOCK_DGRAM - 使用不连续不可信赖的数据包连接
	// NETLINK_KOBJECT_UEVENT - 内核消息到用户空间,出现在 Linux 2.6.10
	nSockFd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
	if (-1 == nSockFd)
	{
		return -1;
	}
	
	// 3.设置套接字接收缓冲区大小
	// SOL_SOCKET - 存取 socket 层
	// SO_RCVBUF  - 设置接收缓冲区大小
	// 接收内核发来的消息缓冲区大小
	const s32 nRcvBufSize = 1024;
	setsockopt(nSockFd, SOL_SOCKET, SO_RCVBUF, &nRcvBufSize, sizeof(nRcvBufSize));
	
	// 4.将套接字加入指定的多播组
	s32 nResult = ::bind(nSockFd, (struct sockaddr*)&snl, sizeof(snl));
	if (-1 == nResult)
	{
		close(nSockFd);
		return -2;
	}

#endif

	return nSockFd;
}

上面定义了套接口,以及进行了绑定,下面是接收数据:

void ReceiveUsbMsg(s32 nSockFd)
{
	if (nSockFd <= 0)
	{
		return;
	}

	// 接收内核发来的消息字符串
	s8 achKernelMsg[1024] = { 0 };

	// 接收内核消息 (一条消息里有多个字符串,并且字符串之间有截止符'\0'隔开)
	s32 recvbytes = recv(nSockFd, achKernelMsg, sizeof(achKernelMsg), 0);
	if (recvbytes == 0)
	{  
		return;
	}
	else if (recvbytes < 0)
	{  
		return;
	}
	else
	{
		//进行数据处理
	}
}

设置socket的接收缓冲区的大小和获取接收缓冲区的大小

#include <sys/types.h>
#include <sys/socket.h>
 
Int getsockopt(int sockfd, int level, int optname,
            void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
            const void *optval, socklen_t optlen);  //设置直接是socklen_t,同int
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
	int sock_fd = -1;
	//建立socket套接字
	sock_fd = socket(AF_INET, SOCK_DGRAM,0);
	if( -1 == sock_fd )
	{
		perror("socket");
		exit(1);
	}

	int recv_get_size = 0;
	int len = sizeof(int);

	getsockopt( sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_get_size, (socklen_t*)&len);
	printf("default recvbuf size: %dk\n", recv_get_size/1024);

	const int recv_set_size = 1024;
	setsockopt( sock_fd, SOL_SOCKET, SO_RCVBUF, (void*)&recv_set_size, len);

	getsockopt( sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_get_size, (socklen_t*)&len);
	printf("set get recvbuf size: %dk\n", recv_get_size/1024);

	close(sock_fd);
	return 0;
}

允许结果如下:

default recvbuf size: 208k
set get recvbuf size: 2k

目前最小缓冲区是2k,设置512字节之后,再获取缓冲区大小还是2k