协议栈数据发送
来源:互联网 发布:mac obs 插件 编辑:程序博客网 时间:2024/06/06 06:30
传输层的数据发送
传输层的数据发送的触发
1、由用户进程下一次send系统调用
2、协议栈收到数据反馈后执行数据的发送
tcp_write_xmit(){
while ((skb = tcp_send_head(sk)))
{
tcp_event_new_data_sent(sk, skb);//重新获取首部
}
}
数据发送经过ip层路由和邻居协议后
发送队列关联了Qdiscnet/core/Dev.cint dev_queue_xmit(struct sk_buff *skb){struct net_device *dev = skb->dev;//ip层路由的时候,会计算得到包的出口设备struct netdev_queue *txq;struct Qdisc *q;txq = dev_pick_tx(dev, skb);q = rcu_dereference(txq->qdisc);if (q->enqueue) {rc = __dev_xmit_skb(skb, q, dev, txq);goto out;}}多队列网卡需要选择从哪个队列出去net/core/Dev.cstatic struct netdev_queue *dev_pick_tx(struct net_device *dev,struct sk_buff *skb){const struct net_device_ops *ops = dev->netdev_ops;u16 queue_index = 0;if (ops->ndo_select_queue)queue_index = ops->ndo_select_queue(dev, skb);else if (dev->real_num_tx_queues > 1)queue_index = skb_tx_hash(dev, skb);skb_set_queue_mapping(skb, queue_index);return netdev_get_tx_queue(dev, queue_index);}将包放入到Qdisc中net/core/dev.cstatic inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, struct net_device *dev,struct netdev_queue *txq){ .....rc = qdisc_enqueue_root(skb, q);qdisc_run(q); .....return rc;}
static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch){ return sch->enqueue(skb, sch);}static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch){ qdisc_skb_cb(skb)->pkt_len = skb->len; return qdisc_enqueue(skb, sch) & NET_XMIT_MASK;}
启动发送的软中断net/sched/sch_generic.cvoid __qdisc_run(struct Qdisc *q){unsigned long start_time = jiffies;while (qdisc_restart(q)) {if (need_resched() || jiffies != start_time) {__netif_schedule(q);break;}}clear_bit(__QDISC_STATE_RUNNING, &q->state);}net/core/dev.cstatic inline void __netif_reschedule(struct Qdisc *q){struct softnet_data *sd;unsigned long flags;local_irq_save(flags);sd = &__get_cpu_var(softnet_data);q->next_sched = sd->output_queue;sd->output_queue = q;raise_softirq_irqoff(NET_TX_SOFTIRQ);local_irq_restore(flags);}net/core/dev.cvoid __netif_schedule(struct Qdisc *q){if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state))__netif_reschedule(q);}
数据即使触发了协议栈的发送,也不会立即出网卡,还要经过Qdisc的流量调节,Qdisc的流量调节是通过软中断来控制
这决定了数据的发送又是一个异步的过程了
用户态=>传输层发送队列=>网卡的多队列或者Qdisc队列
3个环节都是异步执行的
第一个环节是要用户态切换到内核态
第二个环节都是在内核态,只不过后续的数据发送在中断的上下文中处理
0 0
- 协议栈数据发送
- Zigbee协议栈进行数据发送
- linux协议栈之链路层上的数据传输-----数据发送
- UIP协议栈UDP数据发送的问题
- 蓝牙协议栈主从机之间发送数据
- Linux TCP/IP 协议栈数据发送流程
- tcp/ip协议栈--tcp数据发送流程
- UDP协议接收数据与发送数据
- TCP协议发送数据:TCP 协议接收端(服务端)数据,
- linxu kernel version 1.0 TCP/IP 协议栈源代码分析1, UDP协议发送数据.
- 使用UDP协议发送和接收数据
- 使用UDP协议发送和接收数据
- C# 用HTTP协议发送、接收数据
- 通过Http协议发送XML数据
- 使用UDP协议发送和接收数据
- java 实现http协议发送接收数据
- TCP协议接收与发送数据
- 网络编程_UDP协议发送数据
- RSA密钥生成指数和模
- 使用myeclipse高版本时打开编辑jsp卡住假死解决方法
- 使用Palette类提取图片的颜色信息
- csu 1755 阶数(欧拉函数)
- ARM的IIC
- 协议栈数据发送
- spring mvc mybatis 整合
- python—解决“Unable to find vcvarsall.bat”错误
- SQL——JDBC的介绍
- 反射类方法
- 汉诺塔游戏
- 2016.8.10
- 关于图片边距和尺寸问题的几个实用方法
- tomcat 日志log4j,slf4j,logback冲突