2

我在将 netlink 消息从内核模块发送到用户空间守护进程时遇到了很多麻烦。他们随机失败。在内核方面,用户端的genlmsg_unicast失败(函数来自)失败,这是由系统调用失败引起的。EAGAINnl_recvmsgs_defaultlibnlNLE_NOMEMrecvmsgENOBUFS

Netlink 消息很小,最大有效负载大小约为 300B。

这是从内核发送消息的代码:

int send_to_daemon(void* msg, int len, int command, int seq, u32 pid) {
    struct sk_buff* skb;
    void* msg_head;
    int res, payload;

    payload = GENL_HDRLEN+nla_total_size(len)+36;
    skb = genlmsg_new(payload, GFP_KERNEL);
    msg_head = genlmsg_put(skb, pid, seq, &psvfs_gnl_family, 0, command);
    nla_put(skb, PSVFS_A_MSG, len, msg);
    genlmsg_end(skb, msg_head);
    genlmsg_unicast(&init_net, skb, pid);

    return 0;
}

我完全不知道为什么会发生这种情况,因此我的项目将无法正常工作!我真的希望有人可以帮助我。

4

2 回答 2

2

I wonder if you are running on a 64bits machine. If it is the case, I suspect that the use of an int as the type of payload can be the root of some issues as genlmsg_new() expects a size_t which is 64bits on x86_64.

Secondly, I don't think you need to add GENL_HDRLEN to payload as this is taken care of by genlmsg_new() (by using genlmsg_total_size(), which returns genlmsg_msg_size() which finally does the addition). Why this + 36 by the way? Does not look very portable nor explicit on what it is there for.

Hard to tell more without having a look at the rest of the code.

于 2011-12-13T20:27:21.270 回答
2

我在从 netlink 套接字通过 recvmsg 接收 ENOBUFS 时遇到了类似的问题。我发现我的问题是内核套接字缓冲区在用户空间耗尽之前填充。

netlink(7) 手册页

   However, reliable transmissions from kernel to user are impossible in
   any case.  The kernel can't send a  netlink  message  if  the  socket
   buffer  is  full:  the message will be dropped and the kernel and the
   user-space process will no longer have the same view of kernel state.
   It  is  up  to  the  application to detect when this happens (via the
   ENOBUFS error returned by recvmsg(2)) and resynchronize.

我通过增加套接字接收缓冲区的大小(setsockopt(fd, SOL_SOCKET, SO_RCVBUF, ...) 或nl_socket_set_buffer_size()如果您使用 libnl)解决了这个问题。

于 2013-08-09T17:34:17.447 回答