sizeof与strlen的区别(Linux netlink详解)


sizeof与strlen的区别(Linux netlink详解)

对于熟悉Linux wifi的同学来说,wpa_supplicant程序是基于netlink与wifi驱动进行通信的。我们将学习Linux的netlink,并给出用户空间与内核空间基于netlink通信的示例。这些示例包括netlink和generic netlink的使用。用户空间程序将包括基于原生Linux API和基于libnl API的示例。

一、netlink基础

netlink协议是一个基于socket的协议,用于内核与用户空间进程之间的通信。用户态创建netlink socket的代码如下:

c

int fd = socket(AF_NETLINK, SOCK_RAW, MY_NETLINK);

内核态创建netlink socket的接口原型为:

c

struct sock netlink_kernel_create(struct net net, int unit, struct netlink_kernel_cfg cfg);

Netlink消息有固定的格式,包括nlmsghdr、genlmsghdr等结构。

二、关键代码注释

原生Linux API示例

内核侧示例:

c

//定义自己的netlink协议号

define MY_NETLINK 31

//接收回调,即内核侧收到用户发来的netlink消息回调

static void netlink_recv_msg(struct sk_buff skb) { ... }

struct netlink_kernel_cfg cfg = { .input = netlink_recv_msg, };

//创建内核测netlink socket

g_nl_sock = netlink_kernel_create(&init_net, MY_NETLINK, &cfg);

用户侧示例:

c

int main(int argc, char argv[]) {

//创建socket

sock_fd = socket(PF_NETLINK, SOCK_RAW, MY_NETLINK);

...

//绑定端口

bind(sock_fd, (struct sockaddr)&src_addr, sizeof(src_addr));

...

//可以通过sendmsg或sendto两种接口向内核发送消息

libnl API示例:对用户空间原生的netlink API进行了封装,使得用户空间程序更容易编写,尤其是对于generic netlink API。关于generic netlink API的详细介绍将在下文给出。wpa_supplicant与内核wifi驱动的通信就是用的libnl generic netlink API。主要接口定义在头文件中。用户侧示例代码与原生API类似,但使用了libnl提供的函数。内核侧代码不变。基于libnl的示例可参考github链接中的示例代码。generic netlink是netlink的扩展,用于解决协议号不足的问题。generic netlink的消息格式和属性机制将在下文详细解释。内核侧示例代码可参考相关文档和资料。本文示例基于4.15内核版本。本文给出了关于Linux netlink通信的详细解释和示例,包括用户空间和内核空间的示例代码,以及基于libnl API和generic netlink的示例。这些示例将有助于读者更好地理解和应用Linux netlink通信。注册generic netlink家族需要经过以下三个步骤:

第一步:定义操作

你需要定义一些操作,包括属性(attributes)、属性策略(attribute policy)、命令(commands)和操作定义(operation definition)。这些定义包括枚举类型、静态变量和函数等。

这是一个简化的伪代码示例:

第二步:定义family(家族)

在这个步骤中,你需要定义你的netlink家族,包括家族名称、版本、操作、最大属性等。你需要定义处理函数,该函数将在内核接收到用户空间的请求时被调用。伪代码如下:

第三步:注册family(家族)

最后一步是将定义的family注册到内核中。如果注册失败,会返回错误码。伪代码如下:

关于用户空间的示例程序,这个程序需要和内核空间的程序通过netlink进行通信。它首先需要定义与内核相同的属性和命令,然后创建一个netlink socket并连接到对应的generic netlink家族。通过发送和接收netlink消息,用户空间程序可以与内核进行交互。伪代码如下:

关于你的问题,"如果内核不知道用户空间的socket信息,内核如何将消息发送到用户空间呢?" 内核会将消息组播出去,任何订阅了这个组播的用户空间程序都能收到这个消息。具体的实现和示例可能需要更详细的研究和编写,这里无法给出完整的代码示例。

完整的示例代码可以在GitHub上找到,链接已在文中给出。关于组播netlink消息的示例,可能需要你自行查找或等待后续补充。希望这些信息对你有所帮助!


sizeof与strlen的区别(Linux netlink详解)