• sendmsg: no buffer space available


    今天在将项目从虚拟机上移植到真实机器上面的时候,发现问题,总是不成功,最后判断是userspace的程序没有向kernel发送消息成功,因为无法触发kernel的行为,但是userspace显示正常。

    这个问题好像两个月之前,netlink模块测试的时候遇到过这个问题,当时加上sleep就好了,同样复制这个方法,发现使用usleep(1)就解决问题了。

    接下来分析问题的原因,问题锁定在sendmsg上面。

    查看sendmsg的返回值,发现是-1,也就是说sendmsg失败了,看errno: ENOBUFS。

           ENOBUFS
                  The output queue for a network interface was full.  This generally indicates that the interface has stopped sending, but may be caused  by  transient  conges-
                  tion.  (Normally, this does not occur in Linux.  Packets are just silently dropped when a device queue overflows.)


    也就是说发送队列占满了,怎么会出现出现这样的问题呢?

    追踪sendmsg函数:

    sys_sendmsg()

    ......
        err = -ENOBUFS;

        if (msg_sys.msg_controllen > INT_MAX)
            goto out_freeiov;
        ctl_len = msg_sys.msg_controllen;
        if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
            err = cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, sizeof(ctl));
            if (err)
                goto out_freeiov;

    ......
    out_freectl:
        if (ctl_buf != ctl)   
            sock_kfree_s(sock->sk, ctl_buf, ctl_len);
    out_freeiov:
        if (iov != iovstack)
            sock_kfree_s(sock->sk, iov, iov_size);
    out_put:
        fput_light(sock->file, fput_needed);
    out:      
        return err;

    发现在sys_sendmsg中会引用一些msg中的成员变量,一些变量很大导致返回ENOBUFS错误,最终导致no buffer space available。

    看我们的userspace代码:

        struct msghdr msg;

        msg.msg_name = (void *)&dest_addr;
        msg.msg_namelen = sizeof(dest_addr);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;


    OMG,竟然没有初始化,这样的话,msg.msg_controllen就有可能比较大,导致出现ENOBUFS错误。

    解决方法就是初始化msg:

    memset(&msg, 0 ,sizeof(msg));


    注意:在调试内核相关程序的时候,一定要检查返回值,一定要进行初始化,不要想当然。有些编译器会帮你初始化,但是有些不会,程序员不能够依赖编译器来干活 :-)

  • 相关阅读:
    SQLServer2008安装卡在publishing assembly information
    找新朋友
    如何解决:Android中 Error generating final archive: Debug Certificate 的错误
    Open your mind
    A+B Format (20)
    A+B
    1005. Spell It Right (20)
    如何彻底卸载 SQL SERVER
    VC快捷键
    C#之将数据导出到Excel
  • 原文地址:https://www.cnblogs.com/timssd/p/4567909.html
Copyright © 2020-2023  润新知