Netlink套接字捕获的内容

Netlink套接字是用于用户态和内核态之间的通信。同网络协议中的IPV4、IPV6一样,也是通过socket套接字进行创建的,只是往socket里面传入的参数不一样。通过socket创建好套接字后,IPV4这边的TCP和UDP协议是绑定ip地址+端口号,TCP会根据服务端、客服端的不同进行一些设置,比如服务端的主动变被动listen、等待接收消息accept,客户端请求发送的connect等。UDP不分服务端和客户端,只分发送端和接收端,每个终端之间都会作为发送端和接收端,也会进行一些设置。

Netlink这边也是先通过socket创建一个套接字,重点来了,绑定一个地址,一般是当前进程的pid,也就是getpid(),不同于IPV4绑定ip地址+端口号(根据ip地址的需要自己进行变化),Netlink的初始化基本上就定死了,就是这样,这些参数就是固定的,不需要改变。

  9 static int init_hotplug_sock(void)
 10 {   
 11     struct sockaddr_nl snl;
// 定义一个常量整数变量buffersize,表示套接字接收缓冲区的大小为16MB
 12     const int buffersize = 16 * 1024 * 1024;
 13     int retval;
// 创建一个Netlink套接字,协议族为PF_NETLINK,套接字类型为SOCK_DGRAM,协议为NETLINK_KOBJECT_UEVENT
 14     
 15     int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
 16     if (hotplug_sock == -1) {
 17         printf("error getting socket: %s\n", strerror(errno));
 18         return -1;
 19     }
// 设置套接字接收缓冲区大小
 20     
 21     setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
// 初始化snl结构体
 22     
 23     memset(&snl, 0x00, sizeof(struct sockaddr_nl));
 24     snl.nl_family = AF_NETLINK;
 25     snl.nl_pid = getpid();
 26     snl.nl_groups = 1;
// 绑定套接字到指定的地址
 27     
 28     retval = bind(hotplug_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));
 29     if (retval < 0) {
 30         printf("bind failed: %s\n", strerror(errno));
 31         close(hotplug_sock);
 32         hotplug_sock = -1;
 33         return -1;
 34     }
 35     
 36     return hotplug_sock;
 37 }



// 创建一个套接字
int hotplug_sock = init_hotplug_sock();

疑问来了,这个套接字是干嘛的?网上很多原理性从内核方面的解释,本菜鸡刚接触linux这一块,看不太懂,本着会用就行的原则,便直观性的感受一下这个套接字到底是个啥

先放结论,当向开发板插上U盘时,hotpulg_sock会自动捕获这些信息:

当U盘从开发板上拔出时,hotpulg_sock会自动捕获这些信息:

通过这些信息,我们可以进行U盘自动挂载的操作,比如,当检测有“add”的时候,mount 挂载XXX,当检测有“remove”的时候,卸载XXX。

 

记录一下探寻的过程,linux环境编译进行,将生成的可执行文件放在海思开发板上运行,先初始化Netlink套接字,将这个套接字的内容发送给buf,对buf进行打印

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/socket.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;

    int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    if (hotplug_sock == -1) {
        printf("error getting socket: %s\n", strerror(errno));
        return -1;
    }

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

    memset(&snl, 0x00, sizeof(struct sockaddr_nl));
    snl.nl_family = AF_NETLINK;
    snl.nl_pid = getpid();
    snl.nl_groups = 1;

    retval = bind(hotplug_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));
    if (retval < 0) {
        printf("bind failed: %s\n", strerror(errno));
        close(hotplug_sock);
        hotplug_sock = -1;
        return -1;
    }

    return hotplug_sock;
}

int main()
{
    int hotplug_sock = init_hotplug_sock();
    if (hotplug_sock == -1) {
        return 1;
    }

    while (true) {
        char buf[2048];
        int len = recv(hotplug_sock, buf, sizeof(buf), 0);
        if (len > 0) {
            buf[len] = '\0'; // 确保缓冲区以null结尾
            printf("Received message:\n%s\n", buf);

            // 在这里可以添加处理逻辑,例如解析设备添加或移除事件
            if (strstr(buf, "ACTION=add")) {
                printf("Device added:\n");
                printf("%s\n", buf);
            } else if (strstr(buf, "ACTION=remove")) {
                printf("Device removed:\n");
                printf("%s\n", buf);
            }
        } else if (len < 0) {
            printf("recv failed: %s\n", strerror(errno));
            break;
        }
    }

    close(hotplug_sock);
    return 0;
}

使用linux自带的交叉编译工具编译

使用nfs进行文件共享,这地方是将开发板是mnt挂载到了linux的work目录下,在开发板上运行报错:

很纳闷,为啥会报错??第一次意识到了海思快速入门手册里提供的交叉编译工具的作用,使用海思交叉编译工具重新进行编译

重新运行,成功:

往U盘上进行插入和拔出,就会出现最开始的那种现象,把这个套接字的内容打印出来了。

这样的话,开发板上什么也操作不了了,./hotplug_monitor &  这样后台运行会更好一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值