2011-12-03 9 views
2

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

面白いことに、標準のシステムコールrecvnl_socket_get_fd(sock))を使用してnetlinkソケットから直接データを受信すると、すべて正常に機能します!

これはなぜ起こっているのでしょうか?

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); 

ここでは、ユーザ空間プログラムによって送信さmesssageのためのカーネル側のコールバック(これが適切に呼び出される)である:ここで

は、ユーザー空間コードは(parse_cbが呼び出されないコールバックです)です

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; 
} 

答えて

1

OK、私はWHを見つけましたここで間違っていた

libnl関数には、標準のPOSIX戻りコードとは異なる独自のエラーコードがあり、-16はNLE_SEQ_MISMATCHを表します。

この問題は、メッセージに割り当てられた不正なシーケンス番号が原因で発生しています。

+0

これはちょっと遅いですが、私は同じ問題を抱えています。インターネット上の誰もlibnlのドキュメントを更新していません....どのように修正しましたか?コールバック関数がまったく呼び出されていないため、-16のエラーが発生します。私はシーケンス番号を "0"に割り当てています。なぜなら、メッセージを順番に送信することは気にしないからです。 "nl_socket_disable_seq_check"を呼び出すと、コールバック関数はまだ呼び出されませんが、 "nl_recvmsgs_default"は0しか返しません。 – Chris

+0

ポリシーの正確性を確認してください。ポリシー用にメモリを割り当てると、いくらかのゴミが格納され、ネットリンク構造のいくつかのフィールドが間違った値で初期化される可能性があります。また、すべてのメッセージに対してコールバックハンドラを設定していることを確認してください。ハンドラを誤った型に設定する可能性があります。 – t0k3n1z3r

関連する問題