作者:gfree.wind@gmail.com

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

内核中的UDP socket流程(11)——ip_append_data相关推荐

  1. 内核中的UDP socket流程(2)——API “sys_socket”

    内核中的UDP socket流程(2)--API "sys_socket" 作者:gfree.wind@gmail.com 原文:http://blog.chinaunix.net ...

  2. 内核中的UDP socket流程(1)

    内核中的UDP socket流程(1)  相对于TCP,UDP协议要简单的多.所以我决定由简入繁,先从UDP协议入手. 前一遍文章已经确定了struct sk_buff被用于socket的接受和发送缓 ...

  3. 内核中的UDP socket流程(7)——udp_sendmsg

    sock_sendmsg的代码很简单 int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { struct k ...

  4. 内核中的UDP socket流程(5)——inet_create

    进入函数inet_create static int inet_create(struct net *net, struct socket *sock, int protocol,           ...

  5. 内核中的UDP socket流程(3)(4)——sock_create

    好了,闲话少说.上次看到了sys_socket调用sock_create的地方了.下面开始研究sock_create了. sys_socket将自己的参数family, type, protocol传 ...

  6. 内核中的UDP socket流程(6)——sendto

    现在开始新的API sendto,那么就重新回到了socket.c文件. SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, l ...

  7. 一文讲解Linux内核中根文件系统挂载流程

    根文件系统的概念 根文件系统是控制权从linux内核转移到用户空间的一个桥梁.linux内核就类似于一个黑匣子,只向用户提供各种功能的接口,但是功能的具体实现不可见,用户程序通过对这些功能接口的不同整 ...

  8. linux程序获取透传参数,Linux内核中TCP SACK处理流程分析

    frankzfz2014-07-27 17:32 demo121:frankzfz您好: 我想请教一个问题,就是将写好的GenericApp项目(没有配置工具),我加入zigbee协议栈的配置工具后还 ...

  9. Linux内核网络协议栈8—socket监听

    几个问题  了解以下几个问题的同学可以直接忽略下文: 1.listen 库函数主要做了什么?  2. 什么是最大并发连接请求数?  3.什么是等待连接队列? socket 监听相对还是比较简单的,先看 ...

最新文章

  1. Python之迭代器,生成器与装饰器
  2. 数据分析与挖掘 - R语言:贝叶斯分类算法(案例三)
  3. 递归回溯最简单易懂的小例子
  4. 趣挨踢 | 30 个让程序员崩溃的瞬间,笑死我了!
  5. oracle用户密码规则,使用Oracle自带profile以及函数简单设定Oracle用户名密码规则...
  6. java子网划分_IP地址子网划分_动力节点Java学院整理
  7. 2022最新开源分销商城小程序源码系统前端+后端+搭建教程
  8. 【机器人学】机器人运动学基础
  9. cpu发热测试软件,如何检测CPU的温度?这些软件少不了
  10. 什么是面向对象的编程
  11. 程序员讲装修内容思路
  12. faiss 相似特征向量搜索
  13. 三角函数π/2转化_【数学知识点】完整版三角函数诱导公式
  14. js中every用法_详解JavaScript中的every()方法
  15. SLsec题目wp(2)
  16. Spring Boot 自动装配的原理
  17. 第一个Physx例子
  18. softmax函数的硬件实现
  19. 浅谈关于斜率优化中为什么能转换为横截式
  20. 老板键2.0一键隐藏 桌面摸鱼 用于快速隐藏游戏或其他无关工作的程式

热门文章

  1. python grid函数_(转)Python Tkinter Grid布局管理器详解
  2. java freemarker 模版_Java模版引擎Freemarker
  3. dicom是指_dicom格式是什么
  4. java上机实验答案_java上机实验答案与解析
  5. python编写时钟代码_python Tkinter 编写时钟
  6. oracle主备不同步,主备环境下数据不一致重新部署复制
  7. censtos6.5安装java 8_Centos6.5 安装JDK
  8. VB案例:素数判断与合数分解
  9. 【BZOJ1196】公路修建问题,二分+最小生成树
  10. 2.图像作为函数 | 裁剪、颜色通道、图像相加_5