RK3568驱动指南|第十篇 热插拔-第116章netlink监听广播信息实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第十期_热插拔_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第116章netlink监听广播信息实验

在上一章的实验中,我们填充了三个回调函数,分别为.filter = myfilter,  .uevent = myevent,  .name = myname,但在最后的实验中只验证filter过滤了kset中的kobject1,那另外两个回调函数要如何验证呢?

内核通过kobject uevent接口发送广播事件之后,用户空间可以通过netlink来监听这些广播信息。通过监听广播信息,就可以获取到携带环境变量的事件,在本章节将会对netlink进行详细的讲解。

116.1 netlink机制介绍

Netlink是Linux内核中用于内核和用户空间之间进行双工通信的机制。它基于socket通信机制,并提供了一种可靠的、异步的、多播的、有序的通信方式。

Netlink机制的主要特点包括:

(1)双工通信:Netlink允许内核和用户空间之间进行双向通信,使得内核可以向用户空间发送消息,同时也可以接收来自用户空间的消息。

(2)可靠性:Netlink提供了可靠的消息传递机制,保证消息的完整性和可靠性。它使用了确认和重传机制,以确保消息的可靠传输。

(3)异步通信:Netlink支持异步通信,即内核和用户空间可以独立地发送和接收消息,无需同步等待对方的响应。

(4)多播支持:Netlink允许向多个进程或套接字广播消息,以实现一对多的通信。

(5)有序传输:Netlink保证消息的有序传输,即发送的消息按照发送的顺序在接收端按序接收。

Netlink的应用广泛,常见的应用包括:

(1)系统管理工具:如ifconfig、ip等工具使用Netlink与内核通信来获取和配置网络接口的信息。

(2)进程间通信:进程可以使用Netlink进行跨进程通信,实现进程间的数据交换和协调。

(3)内核模块和用户空间应用程序的通信:内核模块可以通过Netlink向用户空间应用程序发送通知或接收用户空间应用程序的指令。

116.2 netlink的使用

116.2.1 创建socket

在Linux socket编程中,创建套接字是构建网络应用程序的第一步。套接字可以理解为应用程序和网络之间的桥梁,用于在网络上进行数据的收发和处理。该系统调用的原型和所需头文件如下所示:

所需头文件

函数原型

#include <sys/types.h>          

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

其中,domain参数指定了套接字的协议族,type参数指定了套接字的类型,protocol参数指定了套接字所使用的具体协议。下面分别介绍这三个参数的含义:

(1)协议族

协议族指定了套接字所使用的协议类型,常用的协议族包括AF_INET、AF_INET6、AF_UNIX等。其中,AF_INET表示IPv4协议族,AF_INET6表示IPv6协议族,AF_UNIX表示Unix域协议族,这里的协议族为netlink,所以该参数要在程序中设置为AF_ NETLINK。

(2)套接字类型

套接字类型指定了套接字的数据传输方式,常用的套接字类型包括SOCK_STREAM、SOCK_DGRAM、SOCK_RAW等。其中,SOCK_STREAM表示面向连接的流套接字,主要用于可靠传输数据,例如TCP协议。SOCK_DGRAM表示无连接的数据报套接字,主要用于不可靠传输数据,例如UDP协议。在本实验中该参数要设置为SOCK_RAW表示原始套接字,可以直接访问底层网络协议。

(3)协议类型

协议类型指定了套接字所使用的具体协议类型,常用的协议类型包括IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP等。其中,IPPROTO_TCP表示TCP协议,IPPROTO_UDP表示UDP协议,IPPROTO_ICMP表示ICMP协议,在本实验中,我们要设置为NETLINK_ _KOBJECT_ UEVENT

在本小节中将使用以下代码创建一个新的套接字:

1 

int socket_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);

AF_NETLINK:指定了使用Netlink协议族。Netlink协议族是一种Linux特定的协议族,用于内核和用户空间之间的通信。

SOCK_RAW:指定了创建原始套接字,这种套接字类型可以直接访问底层协议,而不需要进行协议栈处理。在这种情况下,我们可以直接使用Netlink协议进行通信。

NETLINK_KOBJECT_UEVENT:指定了Netlink协议的一种类型,即kobject uevent类型。kobject uevent用于内核对象相关的事件通知,当内核中的kobject对象发生变化时,会通过此类型的Netlink消息通知用户空间。

116.2.2绑定套接字

创建套接字后,需要将其与一个网络地址绑定,以便其他计算机可以访问该套接字。在Linux系统下,可以使用bind()系统调用绑定套接字和地址。该系统调用的原型和所需头文件如下所示:

所需头文件

函数原型

1 

2

#include <sys/types.h>          

#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr,

socklen_t addrlen);

  1. sockfd参数指定了需要绑定的套接字描述符,
  2. addr参数指定了需要绑定的地址信息,这里使用sockaddr_nl结构体,sockaddr_nl结构体的定义如下:
struct sockaddr_nl {sa_family_t nl_family;  // AF_NETLINKunsigned short nl_pad;  // zerouint32_t nl_pid;        // port IDuint32_t nl_groups;     // multicast groups mask
};

nl_family:表示地址族,此处固定为AF_NETLINK,指示使用Netlink协议族。

nl_pad:填充字段,设置为0。在结构体中进行字节对齐时使用。

nl_pid:端口ID,表示进程的标识符。可以将其设置为当前进程的PID,也可以设为0,表示不加入任何多播组。

nl_groups:多播组掩码,用于指定感兴趣的多播组。当设置为1时,表示用户空间进程只会接收内核事件的基本组的内核事件。这意味着,用户空间进程将只接收到属于基本组的内核事件,而不会接收其他多播组的事件。

  1. addrlen参数:addrlen参数是一个整数,指定了addr所指向的结构体对应的字节长度。它用于确保正确解析传递给addr参数的结构体的大小。

具体编程示例如下所示:

struct sockaddr_nl *nl;  // 定义一个指向 struct sockaddr_nl 结构体的指针 nlbzero(nl, sizeof(struct sockaddr_nl));  // 将 nl 指向的内存区域清零,确保结构体的字段初始化为0nl->nl_family = AF_NETLINK;  // 设置 nl 结构体的 nl_family 字段为 AF_NETLINK,指定地址族为 Netlink
nl->nl_pid = 0;  // 设置 nl 结构体的 nl_pid 字段为 0,表示目标进程 ID 为 0,即广播给所有进程
nl->nl_groups = 1;  // 设置 nl 结构体的 nl_groups 字段为 1,表示只接收基本组的内核事件ret = bind(socket_fd, (struct sockaddr *)nl, sizeof(struct sockaddr_nl));  // 使用 bind 函数将 socket_fd 套接字与 nl 地址结构体绑定在一起if (ret < 0) {printf("bind error\n");return -1;
}

116.2.3接收数据

Netlink套接字在接收数据时不需要调用listen函数,而是可以直接使用recv函数进行接收。下面是recv函数的相关说明:

头文件:

#include <sys/types.h>
#include <sys/socket.h>

函数原型:

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

函数参数:

sockfd:指定套接字描述符,即要接收数据的Netlink套接字。

buf:指向数据接收缓冲区的指针,用于存储接收到的数据。

len:指定要读取的数据的字节大小。

flags:指定一些标志,用于控制数据的接收方式。通常情况下,可以将其设置为0。

返回值:

成功情况下,返回实际读取到的字节数。

如果返回值为0,表示对方已经关闭了连接。

如果返回值为-1,表示发生了错误,可以通过查看errno变量来获取具体的错误代码。

使用recv函数可以从指定的Netlink套接字中接收数据,并将其存储在提供的缓冲区中。函数的返回值表示实际读取到的字节数,可以根据返回值来判断是否成功接收到数据。

接收数据的具体代码示例如下所示:

while (1) {bzero(buf, 4096);  // 将缓冲区 buf 清零,确保数据接收前的初始化len = recv(socket_fd, &buf, 4096, 0);  // 从 socket_fd 套接字接收数据,存储到缓冲区 buf 中,最大接收字节数为 4096for (i = 0; i < len; i++) {if (*(buf + i) == '\0') {  // 如果接收到的数据中有 '\0' 字符,将其替换为 '\n',以便在打印时换行显示buf[i] = '\n';}}printf("%s\n", buf);  // 打印接收到的数据
}

116.3 实验程序的编写

本应用程序对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\80_netlink

根据上一小节所讲解的内容,使用netlink监听广播信息的应用程序netlink.c.c代码如下所示:

#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>int main(int argc, char *argv[]) {int ret;struct sockaddr_nl *nl;  // 定义一个指向 struct sockaddr_nl 结构体的指针 nlint len = 0;char buf[4096] = {0};  // 数据接收缓冲区int i = 0;bzero(nl, sizeof(struct sockaddr_nl));  // 将 nl 指向的内存区域清零,确保结构体的字段初始化为0nl->nl_family = AF_NETLINK;  // 设置 nl 结构体的 nl_family 字段为 AF_NETLINK,指定地址族为 Netlinknl->nl_pid = 0;  // 设置 nl 结构体的 nl_pid 字段为 0,表示目标进程 ID 为 0,即广播给所有进程nl->nl_groups = 1;  // 设置 nl 结构体的 nl_groups 字段为 1,表示只接收基本组的内核事件int socket_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);  // 创建一个 Netlink 套接字if (socket_fd < 0) {printf("socket error\n");return -1;}ret = bind(socket_fd, (struct sockaddr *)nl, sizeof(struct sockaddr_nl));  // 使用 bind 函数将 socket_fd 套接字与 nl 地址结构体绑定在一起if (ret < 0) {printf("bind error\n");return -1;}while (1) {bzero(buf, 4096);  // 将缓冲区 buf 清零,确保数据接收前的初始化len = recv(socket_fd, &buf, 4096, 0);  // 从 socket_fd 套接字接收数据,存储到缓冲区 buf 中,最大接收字节数为 4096for (i = 0; i < len; i++) {if (*(buf + i) == '\0') {  // 如果接收到的数据中有 '\0' 字符,将其替换为 '\n',以便在打印时换行显示buf[i] = '\n';}}printf("%s\n", buf);  // 打印接收到的数据}return 0;
}

116.4 运行测试

116.4.1 编译应用程序

下面进行应用程序编译,因为测试APP是要在开发板上运行的,所以需要aarch64-linux-gnu-gcc来编译,输入以下命令,编译完成以后会生成一个netlink的可执行程序,如下图(图116-1)所示:

aarch64-linux-gnu-gcc -o netlink netlink.c

图 116-1

下面进行程序的测试。

116.4.2 运行测试

本小节测试所使用的驱动文件为上一章编译生成的uevent_ops.ko,应用程序为上一小节编译出来的netlink。

开发板启动之后,首先使用以下命令让应用程序在后台运行,如下图(图116-2)所示:

./netlink &

图 116-2

然后继续使用以下命令加载uevent_ops.ko驱动,打印如下图(116-3)所示:

insmod uevent_ops.ko

图 116-3

SUBSYSTEM=my_kset,表示设备或对象所属的子系统。在这里,子系统是 "my_kset"。MYDEVICE表示设备的名称或标识。在这里,设备的名称是 "TOPEET",正是我们在回调函数中所设置的。

最后可以使用以下命令进行驱动的卸载,如下图(图116-4)所示:

rmmod uevent_ops.ko 

图 116-4

至此,使用netlink监听广播信息实验就完成了。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/339607.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python ASCCI及colorama文本颜色输出

目录 colorama 安装colorama colorama函数应用样例 输出 转义序列颜色 \033 ASCII码颜色输出样例 输出 扩展 将颜色文件制作成模版&#xff0c;即模块 新建一个测试的文件 ColorTest&#xff0c;导入模块DefaultColor 输出 colorama Colorama是一个Python库&…

K8s---存储卷(动态pv和pvc)

当我要发布pvc可以生成pv&#xff0c;还可以共享服务器上直接生成挂载目录。pvc直接绑定pv。 动态pv需要两个组件 1、卷插件&#xff1a;k8s本生支持的动态pv创建不包括nfs&#xff0c;需要声明和安装一个外部插件 Provisioner: 存储分配器。动态创建pv,然后根据pvc的请求自动…

利用gulp工具对常规web项目进行压缩打包

前言 对于一个常规的web项目&#xff0c;如下项目目录 |- imgs | - img1.png | - img2.png |- js | - user.js | - utils.js |- css | - index.css | - user.css |- html | - user.html |- index.html可以使用各种构建工具&#xff08;如webpack、gulp、grunt等&#xff09;来…

话题浏览暴涨558%!从DIY到爆改,小红书数据洞察用户关注焦点

最近走红的“爆改”你们听说了吗&#xff1f;各大社媒平台明星爆改、素人爆改&#xff0c;频上热门。改造风流行的小红书&#xff0c;热度更盛&#xff0c;从DIY到爆改&#xff0c;用户关注焦点是什么&#xff1f;博主和品牌如何讲述“改造”&#xff1f;通过数据分析&#xff…

【Linux】 nohup命令使用

nohup命令 nohup是Linux和Unix系统中的一个命令&#xff0c;其作用是在终端退出时&#xff0c;让进程在后台继续运行。它的全称为“no hang up”&#xff0c;意为“不挂起”。nohup命令可以让你在退出终端或关闭SSH连接后继续运行命令。 nohup 命令&#xff0c;在默认情况下&…

明年评职称,现在就要准备论文了吗?

明年评职称不仅需要提前补好继续教育课时&#xff0c;同样的还需要准备好论文和业绩材料&#xff0c;初级职称的相对来说对论文和业绩要求不高&#xff0c;但是中高级职称业绩和论文的质量代表着你的评审通过率&#xff0c;那为什么需要提前准备好呢&#xff1f;甘建二再给大家…

创建ROS模型与小机器人地图规划

1、打开自己的VM系统 2、安装小机器人的安装包&#xff0c;输入如下命令&#xff0c;回车输入密码(自己设的)&#xff1a; sudo apt install ros-noetic-turtlebot3-simulations ros-noetic-turtlebot3-slam ros-noetic-turtlebot3-navigation 提示我之前安装过了 3、用rosla…

17_网络编程

文章目录 网络数据传输的基本原理UDP发送端步骤接收端步骤DatagramSocketDatagramPacket举例版本1&#xff1a;发送端发送消息,接收端接收并打印版本2&#xff1a;创建一个NetworkUtils工具类优化版本1版本3&#xff1a;发送端接收端相互发送版本4&#xff1a;使用多线程 TCP客…

湘鄂赣三省职称互认,这个消息是真的吗?

甘建二今天明确告诉大家&#xff0c;是真的&#xff0c;这个是属实的&#xff0c;就是说湖南、湖北、江西三地职称是互认的。 2022年就有文件出来了&#xff0c;说的就是三省职称互认&#xff0c;具体看文件&#xff1a; 职称原则都是互相认可&#xff0c;通用的&#xff0c;所…

Alphafold2蛋白质结构预测AI工作站配置推荐

AlphaFold2计算特点 蛋白质三维结构预测是一项计算量非常巨大的任务&#xff0c;科学家多年的探索研究&#xff0c;形成了X射线晶体学法、核磁共振法、冷冻电镜等。 2021年底&#xff0c;谷歌的DeepMind团队的采用人工智能方法的AlphaFold2算法在生物界引起了极大的轰动…

18-链表-移除链表元素

这是链表的第18题&#xff0c;力扣链接。 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,…

PHP短链接url还原成长链接

在开发过程中&#xff0c;碰到了需要校验用户回填的短链接是不是系统所需要的&#xff0c;于是就需要还原找出短链接所对应的长链接。 长链接转短链接 在百度上搜索程序员&#xff0c;跳转页面后的url就是一个长链接。当然你可以从任何地方复制一个长链接过来。 长链接 http…