3

私はいくつかの基本的なカーネル モジュールをコーディングしようとしています - netlink ソケット (ユーザー側の libnl) を使用したユーザー空間プログラム通信。ユーザー空間プログラムはカーネルにメッセージを送信し、応答を期待します。残念ながら、応答の受信は戻り値 -16 (EBUSY) で失敗します。

興味深いことに、標準のシステム コールrecvonを使用して netlink ソケットから直接データを受信するとnl_socket_get_fd(sock)、すべて正常に動作します。

なぜこれが起こっているのか誰にも分かりますか?

ユーザー空間のコードは次のとおりです (parse_cb は呼び出されないコールバックです)。

struct nl_sock *sock;
struct nl_msg *msg;
int family, res;

// Allocate a new netlink socket
sock = nl_socket_alloc();

// Connect to generic netlink socket on kernel side
genl_connect(sock);

// Ask kernel to resolve family name to family id
family = genl_ctrl_resolve(sock, PSVFS_FAMILY_NAME);

// Construct a generic netlink by allocating a new message, fill in
// the header and append a simple integer attribute.
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO,
        PSVFS_C_INIT, PSVFS_VERSION);
nla_put_string(msg, PSVFS_A_MSG, "stuff");

// Send message over netlink socket
nl_send_auto_complete(sock, msg);

// Free message
nlmsg_free(msg);

nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL);

res = nl_recvmsgs_default(sock);
printf("After receive %i.\n", res);

これは、ユーザー空間プログラムによって送信されたメッセージのカーネル側コールバックです (これは適切に呼び出されます)。

int psvfs_vfs_init(struct sk_buff *skb2, struct genl_info *info) {
    send_to_daemon("VFS initialized.", PSVFS_C_INIT, info->snd_seq+1, info->snd_pid);

    return 0;
}

そして、「send_to_daemon」関数は次のとおりです。

int send_to_daemon(char* msg, int command, int seq, u32 pid) {
    int res = 0;
    struct sk_buff* skb;
    void* msg_head;

    skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
    if (skb == NULL) {
        res = -ENOMEM;
        goto out;
    }

    msg_head = genlmsg_put(skb, 0, seq, &psvfs_gnl_family, 0, command);
    if (msg_head == NULL) {
        res = -ENOMEM;
        goto out;
    }

    res = nla_put_string(skb, PSVFS_A_MSG, msg);
    if (res != 0)
        goto out;

    genlmsg_end(skb, msg_head);

    res = genlmsg_unicast(&init_net, skb, pid);
    if (res != 0)
        goto out;

  out:
    return res;
}
4

1 に答える 1

3

OK、ここで何が間違っているかを見つけました。

最終的に、libnl関数には標準の POSIX リターン コードとは異なる独自のエラー コードがあり、-16 は を表すことがわかりましたNLE_SEQ_MISMATCH

この問題は、メッセージに割り当てたシーケンス番号の誤りが原因でした。

于 2011-12-10T20:49:50.270 に答える