2

カーネル モジュールからユーザー空間デーモンに netlink メッセージを送信するのに多くの問題があります。それらはランダムに失敗します。カーネル側では、ユーザー側では(function from ) が失敗し、syscall が で失敗し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

64ビットマシンで実行しているのだろうか。その場合、x86_64で64ビットであると予想されるようintに、タイプとしてのaの使用payloadがいくつかの問題の原因になる可能性があると思います。genlmsg_new()size_t

第二に、これはによって処理されるので、追加GENL_HDRLENする必要はないと思います(を使用して、最終的に追加を行います)。ちなみになぜこれ?それが何のためにあるのかについて、あまり移植性がなく、明確にも見えません。payloadgenlmsg_new()genlmsg_total_size()genlmsg_msg_size()+ 36

コードの残りの部分を見ずに詳細を伝えるのは難しい。

于 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, ...) 、またはlibnl を使用している場合はnl_socket_set_buffer_size() )のサイズを大きくすることで対処しました。

于 2013-08-09T17:34:17.447 に答える