首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有timeout =0的recvmmsg()等效于非阻塞recvmsg()?

具有timeout =0的recvmmsg()等效于非阻塞recvmsg()?
EN

Stack Overflow用户
提问于 2014-09-29 04:05:24
回答 4查看 2.6K关注 0票数 1

我在CentOS 6.5上使用内核版本内核-2.6.32-431.el6。

我试图找到recvmmsg()的实现,希望我没有看错源~/rpmbuild/BUILD/kernel-2.6.32-431.el6/linux-2.6.32-431.el6.x86_64/net/socket.c.如果我是,请告诉我正确的来源。

代码语言:javascript
运行
复制
int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
                   unsigned int flags, struct timespec *timeout)
{
        int fput_needed, err, datagrams;
        struct socket *sock;
        struct mmsghdr __user *entry;
        struct compat_mmsghdr __user *compat_entry;
        struct msghdr msg_sys;
        struct timespec end_time;

        if (timeout &&
            poll_select_set_timeout(&end_time, timeout->tv_sec,
                                    timeout->tv_nsec))
                return -EINVAL;

        datagrams = 0;

        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                return err;

        err = sock_error(sock->sk);
        if (err)
                goto out_put;

        entry = mmsg;
        compat_entry = (struct compat_mmsghdr __user *)mmsg;

        while (datagrams < vlen) {
                /*
                 * No need to ask LSM for more than the first datagram.
                 */
                if (MSG_CMSG_COMPAT & flags) {
                        err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
                                            &msg_sys, flags, datagrams);
                        if (err < 0)
                                break;
                        err = __put_user(err, &compat_entry->msg_len);
                        ++compat_entry;
                } else {
                        err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
                                            &msg_sys, flags, datagrams);
                        if (err < 0)
                                break;
                        err = put_user(err, &entry->msg_len);
                        ++entry;
                }

                if (err)
                        break;
                ++datagrams;

                if (timeout) {
                        ktime_get_ts(timeout);
                        *timeout = timespec_sub(end_time, *timeout);
                        if (timeout->tv_sec < 0) {
                                timeout->tv_sec = timeout->tv_nsec = 0;
                                break;
                        }

                        /* Timeout, return less than vlen datagrams */
                        if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
                                break;
                }

                /* Out of band data, return right away */
                if (msg_sys.msg_flags & MSG_OOB)
                        break;
        }

out_put:
        fput_light(sock->file, fput_needed);

        if (err == 0)
                return datagrams;

        if (datagrams != 0) {
                /*
                 * We may return less entries than requested (vlen) if the
                 * sock is non block and there aren't enough datagrams...
                 */
                if (err != -EAGAIN) {
                        /*
                         * ... or  if recvmsg returns an error after we
                         * received some datagrams, where we record the
                         * error to return on the next call or if the
                         * app asks about it using getsockopt(SO_ERROR).
                         */
                        sock->sk->sk_err = -err;
                }

                return datagrams;
        }

        return err;
}

假设套接字上有两个数据包,我试着:

代码语言:javascript
运行
复制
timespec t = {0, 0};
recvmmsg(fd, mmsg, vlen, 0, &t);

然后,因为这些行:

代码语言:javascript
运行
复制
                    if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
                            break;

recvmmsg()只返回一个包而不是两个包,对吗?

它似乎背离了recvmmsg()的主要目的之一--试图在数据包排队时减少#系统调用。

也许我错过了什么?

任何建议都是欢迎的。

谢谢!

============================

更新:

我试图编写一个小的代码片段,它等待数据包排队,然后用timeout=0 ( NULL)调用recvmmsg()。它仍然只捡到一个包。因此,我认为我看到的是正确的源代码。

EN

回答 4

Stack Overflow用户

发布于 2017-03-29 11:55:02

是的,你是对的。我认为如果要读取队列中的所有数据包,最好使用空超时+ O_NONBLOCK。

票数 1
EN

Stack Overflow用户

发布于 2014-09-29 04:12:26

不是的。零超时意味着无穷大。

票数 0
EN

Stack Overflow用户

发布于 2020-10-31 10:19:01

忽略recvmmsg超时参数,必要时使用SOL_SOCKET、SO_RCVTIMEO。工作正常。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26092379

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档