Netlink:从内核发送到用户-EAGAIN和ENOBUFS [英] Netlink: sending from kernel to user - EAGAIN and ENOBUFS
问题描述
从内核模块向用户空间守护程序发送netlink消息时遇到很多麻烦.他们随机失败.在内核方面,genlmsg_unicast
失败,并出现EAGAIN
;而在用户方面,nl_recvmsgs_default
(来自libnl
的函数)失败,出现NLE_NOMEM
,这是由于recvmsg
系统调用失败并导致ENOBUFS
引起的.
I'm having a lot of trouble sending netlink messages from kernel module to userspace-daemon. They randomly fail. On the kernel side, the genlmsg_unicast
fails with EAGAIN
while on the user-side, nl_recvmsgs_default
(function from libnl
) fails with NLE_NOMEM
which is caused by recvmsg
syscall failing with ENOBUFS
.
Netlink消息很小,最大有效负载大小约为300B.
Netlink messages are small, maximum payload size is ~300B.
这是从内核发送消息的代码:
Here is the code for sending message from kernel:
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;
}
我绝对不知道为什么会这样,而我的项目也因此而无法正常工作!我真的希望有人可以帮助我.
I absolutely have no idea why this is happening and my project just won't work because of that! I really hope someone could help me with that.
推荐答案
我在通过netvm套接字通过recvmsg接收ENOBUFS时遇到类似的问题.我发现我的问题是内核套接字缓冲区在用户空间耗尽之前就已填充.
I was having a similar problem receiving ENOBUFS via recvmsg from a netlink socket. I found that my problem was the kernel socket buffer filling before userspace could drain it.
在 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 ).
I addressed this problem by increasing the size of the socket receive buffer (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, ...) , or nl_socket_set_buffer_size() if you are using libnl).
这篇关于Netlink:从内核发送到用户-EAGAIN和ENOBUFS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!