应用进程使用TCP发送的数据会先放入发送缓存中,TCP的发送缓存是一个skb队列。这个队列存在的意义是:保证应用进程交付TCP的数据能够可靠地交付目的端。在收到对端的ACK之前,发送缓存中的数据不能删除。
10.2.1 使用缓存
对发送缓存的使用是从tcp_sendmsg函数开始的:
1016 int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1017 size_t size)
1018 {
1019 struct iovec *iov;
1020 struct tcp_sock *tp = tcp_sk(sk);
1021 struct sk_buff *skb;
1022 int iovlen, flags, err, copied = 0;
1023 int mss_now = 0, size_goal, copied_syn = 0, offset = 0;
1024 bool sg;
1025 long timeo;
...
1106 if (copy <= 0) {
1107 new_segment:
1108 /* Allocate new segment. If the interface is SG,
1109 * allocate skb fitting to single page.
1110 */
1111 if (!sk_stream_memory_free(sk)) //检查已占用内存是否达到限制
1112 goto wait_for_sndbuf;
1113
1114 skb = sk_stream_alloc_skb(sk,
1115 select_size(sk, sg),
1116 sk->sk_allocation); //申请内存
1117 if (!skb)
1118 goto wait_for_memory;
...
1133 skb_entail(sk, skb);
...
1149 } else { //使用skb的非线性区
1150 bool merge = true;
1151 int i = skb_shinfo(skb)->nr_frags;
1152 struct page_frag *pfrag = sk_page_frag(sk);
1153
1154 if (!sk_page_frag_refill(sk, pfrag))
1155 goto wait_for_memory;
...
1168 if (!sk_wmem_schedule(sk, copy))
1169 goto wait_for_memory;
1170
1171 err = skb_copy_to_page_nocache(sk, from, skb,
1172 pfrag->page,
1173 pfrag->offset,
1174 copy);
sk_stream_memory_free
函数:
743 static inline bool sk_stream_memory_free(const struct sock *sk)
744 {
745 return sk->sk_wmem_queued < sk->sk_sndbuf;
746 } <