drivemyself 发表于 2016-03-15 20:07

关于sendto何时返回用户空间

本帖最后由 drivemyself 于 2016-03-15 20:13 编辑

小弟粗略的看了一下内核中的网络子系统部分,其中有一事一直不明,望大佬帮忙解惑一下:

用户空间UDP数据包发送调用sendto,最终调用到udp_sendmsg,而udp_sendmsg最终由IP层交给数据链路层,大概流程如下


书上解释sendto是将用户空间数据拷贝到内核空间就返回,并没有等待真正的发送完成数据。

但是,发送流程中在ip层udp_sendmsg肯定没有返回用户空间,其中也就是有个qdisc会触发软中断。才有可能返回用户空间。而我调了一下内核,发现都是在内核真正发送完数据,sendto才返回,是不是书上说的本来就是错的?

到底sendto是在何时返回了用户空间?

二、、、
假如,udp_sendmsg真是在while (qdisc_restart(q)) {
                /*
               * Postpone processing if
               * 1. another process needs the CPU;
               * 2. we've been doing it for too long.
               */
                if (need_resched() || jiffies != start_time) {
                        __netif_schedule(q);
                        break;
                }
        }这段代码时返回的,那在返回用户空间时,软中断是会被再次调用的,不就相当于,在返回用户空间前,发送数据设置的软中断又进行发送了吗?最终不也是等到所有的软中断执行完,即发送完成后才返回的用户空间吗?

nswcfd 发表于 2016-03-16 11:55

从理解概念的角度,可以忽略qdisc。

简单的可以认为stack跟driver的接口就是dev_queue_xmit。
当此函数返回时,协议栈认为发送完成,相应的syscall就可以返回。

qdisc位于dev_queue_xmit内部,至于它什么时候把报文交给driver的xmit接口,那是另外一层调度逻辑。

一般情况下,qdisc->enque把报文送给队列,无论是fifo还是sfq/htb等,就算结束【当前报文】的发送流程了。
可以理解为,在dev_queue_xmit返回之前,尝试调度deque逻辑,把【之前】存放的队列的报文(有可能是当前报文)发送出去。
如果不能全部发完,就schedule一次tx软中断,稍后(可能是下一次enque,也可能是这次syscall返回的时候)继续deque。

drivemyself 发表于 2016-03-16 17:45

回复 2# nswcfd

能不能这样理解,在dev_queue_ximt返回之前,会尝试调用一次dequeue,即尝试通过网卡发送一次数据,如果能发就继续发,如果不能发,就会调度出去,设置软中断。

   

nswcfd 发表于 2016-03-16 18:35

嗯,差不多。只不过不是一次deque,而是一个deque循环。
页: [1]
查看完整版本: 关于sendto何时返回用户空间