关于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;
}
}这段代码时返回的,那在返回用户空间时,软中断是会被再次调用的,不就相当于,在返回用户空间前,发送数据设置的软中断又进行发送了吗?最终不也是等到所有的软中断执行完,即发送完成后才返回的用户空间吗? 从理解概念的角度,可以忽略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。 回复 2# nswcfd
能不能这样理解,在dev_queue_ximt返回之前,会尝试调用一次dequeue,即尝试通过网卡发送一次数据,如果能发就继续发,如果不能发,就会调度出去,设置软中断。
嗯,差不多。只不过不是一次deque,而是一个deque循环。
页:
[1]