检测usb口HotPlug-netlink

为了完成内核空间与用户空间通信,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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C语言程序,用于检测USB设备的热插拔事件: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <linux/netlink.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #define UEVENT_BUFFER_SIZE 2048 int init_hotplug_sock() { const int buffersize = 1024; int ret; struct sockaddr_nl snl; bzero(&snl, sizeof(struct sockaddr_nl)); snl.nl_family = AF_NETLINK; snl.nl_pid = getpid(); snl.nl_groups = 1; int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl)); if (ret < 0) { perror("bind"); close(s); return -1; } return s; } int main(int argc, char* argv[]) { int hotplug_sock = init_hotplug_sock(); if (hotplug_sock < 0) return -1; char buffer[UEVENT_BUFFER_SIZE * 2] = {0}; while (1) { fd_set fds; FD_ZERO(&fds); FD_SET(hotplug_sock, &fds); int ret = select(hotplug_sock + 1, &fds, NULL, NULL, NULL); if (ret < 0) { perror("select"); continue; } if (FD_ISSET(hotplug_sock, &fds)) { memset(buffer, 0, sizeof(buffer)); ret = recv(hotplug_sock, &buffer, sizeof(buffer), MSG_DONTWAIT); if (ret > 0) { printf("Received %d bytes: %s\n", ret, buffer); } } } return 0; } ``` 这个程序创建了一个基于Netlink协议的socket,用于监听内核发出的UEVENT事件。当一个USB设备插入或拔出时,内核会发出一个UEVENT事件,这个程序就可以通过socket接收到这个事件,并进行相应的处理。 注意:这个程序只是一个简单的示例,实际的应用中可能需要根据具体的需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值