内核中的UDP socket流程(11)——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特性 */
- 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;
- }
- 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;
内核中的UDP socket流程(11)——ip_append_data相关推荐
- 内核中的UDP socket流程(2)——API “sys_socket”
内核中的UDP socket流程(2)--API "sys_socket" 作者:gfree.wind@gmail.com 原文:http://blog.chinaunix.net ...
- 内核中的UDP socket流程(1)
内核中的UDP socket流程(1) 相对于TCP,UDP协议要简单的多.所以我决定由简入繁,先从UDP协议入手. 前一遍文章已经确定了struct sk_buff被用于socket的接受和发送缓 ...
- 内核中的UDP socket流程(7)——udp_sendmsg
sock_sendmsg的代码很简单 int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { struct k ...
- 内核中的UDP socket流程(5)——inet_create
进入函数inet_create static int inet_create(struct net *net, struct socket *sock, int protocol, ...
- 内核中的UDP socket流程(3)(4)——sock_create
好了,闲话少说.上次看到了sys_socket调用sock_create的地方了.下面开始研究sock_create了. sys_socket将自己的参数family, type, protocol传 ...
- 内核中的UDP socket流程(6)——sendto
现在开始新的API sendto,那么就重新回到了socket.c文件. SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, l ...
- 一文讲解Linux内核中根文件系统挂载流程
根文件系统的概念 根文件系统是控制权从linux内核转移到用户空间的一个桥梁.linux内核就类似于一个黑匣子,只向用户提供各种功能的接口,但是功能的具体实现不可见,用户程序通过对这些功能接口的不同整 ...
- linux程序获取透传参数,Linux内核中TCP SACK处理流程分析
frankzfz2014-07-27 17:32 demo121:frankzfz您好: 我想请教一个问题,就是将写好的GenericApp项目(没有配置工具),我加入zigbee协议栈的配置工具后还 ...
- Linux内核网络协议栈8—socket监听
几个问题 了解以下几个问题的同学可以直接忽略下文: 1.listen 库函数主要做了什么? 2. 什么是最大并发连接请求数? 3.什么是等待连接队列? socket 监听相对还是比较简单的,先看 ...
最新文章
- Python之迭代器,生成器与装饰器
- 数据分析与挖掘 - R语言:贝叶斯分类算法(案例三)
- 递归回溯最简单易懂的小例子
- 趣挨踢 | 30 个让程序员崩溃的瞬间,笑死我了!
- oracle用户密码规则,使用Oracle自带profile以及函数简单设定Oracle用户名密码规则...
- java子网划分_IP地址子网划分_动力节点Java学院整理
- 2022最新开源分销商城小程序源码系统前端+后端+搭建教程
- 【机器人学】机器人运动学基础
- cpu发热测试软件,如何检测CPU的温度?这些软件少不了
- 什么是面向对象的编程
- 程序员讲装修内容思路
- faiss 相似特征向量搜索
- 三角函数π/2转化_【数学知识点】完整版三角函数诱导公式
- js中every用法_详解JavaScript中的every()方法
- SLsec题目wp(2)
- Spring Boot 自动装配的原理
- 第一个Physx例子
- softmax函数的硬件实现
- 浅谈关于斜率优化中为什么能转换为横截式
- 老板键2.0一键隐藏 桌面摸鱼 用于快速隐藏游戏或其他无关工作的程式
热门文章
- python grid函数_(转)Python Tkinter Grid布局管理器详解
- java freemarker 模版_Java模版引擎Freemarker
- dicom是指_dicom格式是什么
- java上机实验答案_java上机实验答案与解析
- python编写时钟代码_python Tkinter 编写时钟
- oracle主备不同步,主备环境下数据不一致重新部署复制
- censtos6.5安装java 8_Centos6.5 安装JDK
- VB案例:素数判断与合数分解
- 【BZOJ1196】公路修建问题,二分+最小生成树
- 2.图像作为函数 | 裁剪、颜色通道、图像相加_5