3

我以前从事过网络编程工作。但这是我第一次涉足 netlink 套接字。

我选择研究“连接器”类型的 netlink 套接字。与任何内核组件一样,它也有一个用户对应项。linux 内核有一个名为ucon.c的示例程序,可用于基于上述连接器 netlink 套接字构建用户空间程序。

所以在这里我想指出我想确认我理解的程序部分以及我不遵循逻辑的程序部分。说够了。开始了。无论我误入歧途,请纠正我。

据我了解,netlink 套接字是一种 IPC 方法,用于连接同一台机器上的进程,因此进程 ID 用作标识符。由于 netlink 消息可以理想地多播,netlink 套接字需要的另一个标识符是消息组。连接到同一消息组的所有组件实际上都是相关的。因此,在 IPv4 的情况下,我们使用sockaddr_in代替sockaddr,这里我们使用包含上述标识符的sockaddr_nl 。

现在,由于我们不打算使用内核的 TCP/IP 堆栈,所以在 netlink 消息的情况下,netlink数据包可以被认为是原始的(如果我错了,请在这里纠正我)。因此,netlink 数据包经过的唯一封装是定义为nlmsghdr的netlink 消息头

现在进入我们的程序 ucon,首先使用连接器协议main()创建一个 NETLINK 系列套接字。然后它用相关信息填充前面提到的 netlink socketaddress 结构。为了在这里做一点实验,我在 connector.h 文件中添加了一个条目。现在我的第一个问题来了。

连接器消息具有在 connector.h 中定义的特定类型。现在这个连接器消息结构完全是 netlink内部的东西,对吧?就 netlink 而言,这只是有效载荷。正确的?

继续前进,在 netlink 消息头结构中nl-group字段究竟是什么意思?定义实际上并不包含此名称的元素。那么我们是否使用覆盖技术来填充 netlink 消息头的某些字段?如果是这样,对应的具体内容是什么?我似乎无法在任何地方找到它。

因此,在将套接字地址绑定到套接字之后,它会发送 10,000 个基于连接器的唯一数据,就 netlink 而言,这些数据是纯有效负载。但就这些消息而言,奇怪的是,它们似乎都具有相同的序列号。

继续前进,我们发现自己在netlink_send子例程中通过我们上面绑定的套接字发送这些数据包。此子例程使用各种 netlink 帮助宏来操作要发送的数据。正如我们上面所说,该main()函数发送了 10,000 条数据,每条数据长度为零,不需要确认,因为 ack 字段为 0(如果我在这里错了,请纠正我)。因此,每个“数据包”只不过是一个连接器消息头,其中没有任何内容。正确的?

现在令人惊讶的是 netlink_Send 函数使用与 main() 相同的序列号,因为它是一个全局变量。但是,在 main() 中的后增量之后,它现在是“1”。所以基本上我们的netlink 谈话是从序列号“1”开始的。可以吗?

查看 linux/netlink.h 中定义的一些辅助宏,我将尝试总结我对在该程序中直接或间接使用的宏的理解。

#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))

所以这个宏会先对齐netlink消息头长度,然后加上payload长度。对于我们的例子,netlink 有效负载是一个连接器标头,没有任何自己的有效负载。在我们的例子中,这个 micro 是这样使用的

nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));

在这里,我不明白的是netlink消息的实际有效负载。在上述情况下,它是连接器消息头的大小(因为连接器消息本身不包含其自身的有效负载)减去指针(指向 netlink 消息的第一个字节,因此指向 netlink 消息头)。这个指针(像任何其他指针变量一样)等于机器字大小,在我的例子中是 4 个字节。为什么我们要从连接器消息头中减去它?

之后,我们通过这个 netlink 套接字发送消息,就像任何其他 IPv4 套接字一样。关于上述问题,希望能听到各位大侠的来信。在实际问题之前包括一些句子会有所帮助,因为我的帖子相当长。但我希望它对人们有用的不仅仅是我自己。

问候。

4

0 回答 0