作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
继续ip_append_data,
- if (copy > length)
- copy = length;
-
- if (!(rt->dst.dev->features&NETIF_F_SG)) {
- /* 如果网卡不支持Scatter/gather特性,直接拷贝数据 */
- unsigned int off;
-
- off = skb->len;
- if (getfrag(from, skb_put(skb, copy),
- offset, copy, off, skb) 0) {
- __skb_trim(skb, off);
- err = -EFAULT;
- goto error;
- }
- } else {
- /* 如果支持Scatter/gather特性 */
/* 得到已储存的buffer个数 */
- int i = skb_shinfo(skb)->nr_frags;
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
- /* 得到物理页面的地址 */
- struct page *page = sk->sk_sndmsg_page;
- int off = sk->sk_sndmsg_off;
- unsigned int left;
-
- if (page && (left = PAGE_SIZE - off) > 0) {
- /* 该页还有空余空间,可以填充一部分数据 */
/* 如果要拷贝的长度大于剩余空间,调整拷贝的长度 */
- if (copy >= left)
- copy = left;
- if (page != frag->page) {
- /* 此次数据与sock上次缓冲数据不是位于同一物理页面 */
- if (i == MAX_SKB_FRAGS) {
- /* 超过了缓存数据最大个数 */
- err = -EMSGSIZE;
- goto error;
- }
- get_page(page);
- /* 将数据填充到物理页 */
- skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
- frag = &skb_shinfo(skb)->frags[i];
- }
- } else if (i MAX_SKB_FRAGS) {
- /* 将拷贝长度调整为物理页最大值 */
- if (copy > PAGE_SIZE)
- copy = PAGE_SIZE;
- /* 分配一个新的物理页 */
- page = alloc_pages(sk->sk_allocation, 0);
- if (page == NULL) {
- err = -ENOMEM;
- goto error;
- }
- /* 保存物理页地址 */
- sk->sk_sndmsg_page = page;
- sk->sk_sndmsg_off = 0;
/* 填充物理页 */
- skb_fill_page_desc(skb, i, page, 0, 0);
- frag = &skb_shinfo(skb)->frags[i];
- } else {
- err = -EMSGSIZE;
- goto error;
- }
/* 调用getfrag填充数据 */
- if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) 0) {
- err = -EFAULT;
- goto error;
- }
/* 调整各个偏移以及长度 */
- sk->sk_sndmsg_off += copy;
- frag->size += copy;
- skb->len += copy;
- skb->data_len += copy;
- skb->truesize += copy;
- atomic_add(copy, &sk->sk_wmem_alloc);
- }
- /* 继续下一个 */
- offset += copy;
- length -= copy;
- }
-
- return 0;
-
- error:
- inet->cork.length -= length;
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
- return err;
看到这里,这个函数就已经结束了。在之前的学习过程中,有些不明白的问题,或者干脆理解错了的东西,在完全看完这个函数之后,已经有了新的认识。
明天,我会对这些问题进行整理,并总结一下这个函数。