select 源码疑问-请大师帮忙解惑

发布于 2022-10-15 08:54:47 字数 14532 浏览 18 评论 0

我看了 linux下的select源代码 有个困惑,
int select(int nfds, fd_set *readfds, fd_set *writefds,  fd_set *exceptfds, struct timeval *timeout);
第三个参数 是个超时设置, 我看man手册, 如果在时间内 有消息来的话 select会返回. 但是在内核函数里 我没有看到该功能的代码 还请大师们指点一下. 外围代码就不帖了 直接
帖do_select

int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
{
        ktime_t expire, *to = NULL;
        struct poll_wqueues table;
        poll_table *wait;
        int retval, i, timed_out = 0;
        unsigned long slack = 0;

        rcu_read_lock();
        retval = max_select_fd(n, fds);
        rcu_read_unlock();

        if (retval < 0)
                return retval;
        n = retval;

        poll_initwait(&table);
        wait = &table.pt;
        if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
                wait = NULL;
                timed_out = 1;
        }

        if (end_time && !timed_out)
                slack = select_estimate_accuracy(end_time);

        retval = 0;
        for (; {
                unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;

                inp = fds->in; outp = fds->out; exp = fds->ex;
                rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;

                for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
                        unsigned long in, out, ex, all_bits, bit = 1, mask, j;
                        unsigned long res_in = 0, res_out = 0, res_ex = 0;
                        const struct file_operations *f_op = NULL;
                        struct file *file = NULL;

                        in = *inp++; out = *outp++; ex = *exp++;
                        all_bits = in | out | ex;
                        if (all_bits == 0) {
                                i += __NFDBITS;
                                continue;
                        }

                        for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
                                int fput_needed;
                                if (i >= n)
                                        break;
                                if (!(bit & all_bits))
                                        continue;
                                file = fget_light(i, &fput_needed);
                                if (file) {
                                        f_op = file->f_op;
                                        mask = DEFAULT_POLLMASK;
                                        if (f_op && f_op->poll) {
                                                wait_key_set(wait, in, out, bit);
                                                mask = (*f_op->poll)(file, wait);
                                        }
                                        fput_light(file, fput_needed);
                                        if ((mask & POLLIN_SET) && (in & bit)) {
                                                res_in |= bit;
                                                retval++;
                                                wait = NULL;
                                        }
                                        if ((mask & POLLOUT_SET) && (out & bit)) {
                                                res_out |= bit;
                                                retval++;
                                                wait = NULL;
                                        }
                                        if ((mask & POLLEX_SET) && (ex & bit)) {
                                                res_ex |= bit;
                                                retval++;
                                                wait = NULL;
                                        }
                                }
                        }
                        if (res_in)
                                *rinp = res_in;
                        if (res_out)
                                *routp = res_out;
                        if (res_ex)
                                *rexp = res_ex;
                        cond_resched();
                }
                wait = NULL;
                if (retval || timed_out || signal_pending(current))
                        break;
                if (table.error) {
                        retval = table.error;
                        break;
                }

                /*
                 * If this is the first loop and we have a timeout
                 * given, then we convert to ktime_t and set the to
                 * pointer to the expiry value.
                 */
                if (end_time && !to) {
                        expire = timespec_to_ktime(*end_time);
                        to = &expire;
                }

                if (!poll_schedule_timeout(&table, TASK_INTERRUPTIBLE,
                                           to, slack))
                        timed_out = 1;
        }

        poll_freewait(&table);

        return retval;
}

to  好象是失效时间转换成的钠秒, slack表示 到失效时间还剩多少钠秒

poll_schedule_timeout 调用了
nt __sched
schedule_hrtimeout_range_clock(ktime_t *expires, unsigned long delta,
                               const enum hrtimer_mode mode, int clock)
{
        struct hrtimer_sleeper t;

        /*
         * Optimize when a zero timeout value is given. It does not
         * matter whether this is an absolute or a relative time.
         */
        if (expires && !expires->tv64) {
                __set_current_state(TASK_RUNNING);
                return 0;
        }

        /*
         * A NULL parameter means "inifinte"
         */
        if (!expires) {
                schedule();
                __set_current_state(TASK_RUNNING);
                return -EINTR;
        }

        hrtimer_init_on_stack(&t.timer, clock, mode);
        hrtimer_set_expires_range_ns(&t.timer, *expires, delta);

        hrtimer_init_sleeper(&t, current);

        hrtimer_start_expires(&t.timer, mode);
        if (!hrtimer_active(&t.timer))
                t.task = NULL;

        if (likely(t.task))
                schedule();

        hrtimer_cancel(&t.timer);
        destroy_hrtimer_on_stack(&t.timer);

        __set_current_state(TASK_RUNNING);

        return !t.task ? 0 : -EINTR;
}

比如 用 select 看是否有数据可读 , 如果没有 看代码意思 就是会睡眠 直到有信号唤醒它,  socket来数据会唤醒进程吗 代码在哪里实现的这个功能?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

森林很绿却致人迷途 2022-10-22 08:54:47

找到了 好象在这一行  mask = (*f_op->poll)(file, wait);
...

老旧海报 2022-10-22 08:54:47

回复 2# qianhulou

    是的,驱动必须实现POLL_WAIT功能,应用层才能使用SELECT调用。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文