首页 > 解决方案 > 线程中的 netlink 套接字:nl_pid 的值

问题描述

我正在尝试netlinkpthread. 我搜索了一些示例,其中大多数使用以下模式来识别套接字的“本地”端:

struct sockaddr_nl  local = {};
local.nl_family = AF_NETLINK;
local.nl_pid = pthread_self() << 16 | getpid();
...
ret = bind(fd, (struct sockaddr*)&local, sizeof(local));
...

据我了解,通常当每个进程打开一个 netlink 套接字时,nl_pid 设置为 0,内核会选择正确的 portid。但是,对于每个线程的 netlink 情况,情况并非如此,其中PID值将在所有线程之间共享。

此外我认为pthread_self() << 16 | getpid()不便携。在这种情况下设置 nl_pid 的正确方法是什么?

标签: linuxsocketspthreadsnetlink

解决方案


据我了解,通常当每个进程打开一个 netlink 套接字时,nl_pid 设置为 0,内核会选择正确的 portid。但是,对于每个线程的 netlink 情况,情况并非如此,其中 PID 值将在所有线程之间共享。

没有“正确的”端口。使用进程 ID 标识 portid 是一种约定,与内核在分配 portid 时的默认行为一致,而不是规则。应用程序,无论是单线程还是多线程,都可以在允许的端口 ID 范围内自由请求任意端口 ID。

此外,当一个进程(无论是单线程还是多线程)绑定多个 netlink 套接字并将 portid 选择委托给内核时,可以依赖内核为每个进程分配一个唯一的 portid。

此外我认为pthread_self() << 16 | getpid()不便携。

你是对的。为了在一般情况下具有明确定义的行为pthread_t, 的返回类型pthread_self()需要是无符号整数类型,但 POSIX 甚至不要求它是整数,尽管有符号。

Netlink 是特定于 Linux 的,这确实限制了您需要关注的范围。尽管如此,Linux 的 pthreads 实现已经不止一个,未来可能还会有新的实现,并且由于未指定此细节,因此可以想象实现将在版本之间更改类型。

在这种情况下设置 nl_pid 的正确方法是什么?

正如您在评论中总结的那样,我想说选择 netlink portid 的最佳选择几乎总是让内核分配它们。包括在单线程应用程序中。然而,这不是进程的文件描述符表的问题,因为 portid 不是文件描述符。特别是,与文件描述符不同,portid 是系统范围的。这就是让内核选择的更多理由。


推荐阅读