内核版本:linux-2.6.11


本文对Linux网络子系统的收发包的流程进行一个大致梳理,以流水账的形式记录从应用层write一个socket开始到这些数据被应用层read出来的这个过程中linux的网络子系统怎么运作的。
PS:不能保证所有内容都是正确的,同时欢迎指出问题。

发包流程

1)用户进程对一个网络套接字执行write或者send后,该进程通过系统调用进入内核态。

2)在socket这层最终会通过调用sendmsg这个函数将数据传给传输层(这里涉及到使用一个多态的手法来实现不同协议的调用)。

3)接着自顶向下走协议栈的处理流程,以TCP协议为例,tcp_sendmsg作为这个函数接受到发送数据以后将其包装成sk_buff并进行协议处理,包括分组、添加头部、启动定时器等等。

4)传输层处理完以后的包会进入netfilter的NF_IP_LOCAL_OUT hook点。

5)然后将一个个sk_buff传给网络层,如果是IP协议,会进行分片、添加头部、路由判决等操作。同时会进入netfilter的NF_IP_POST_ROUTING点

6)最后,网络层通过调用dev_queue_xmit将处理完并包装好的sk_buff发给驱动程序。
此时,无论是阻塞还是非阻塞模式,write系统调用都会返回,该进程的任务结束。

7)驱动程序在接受到一个待发送的skb后,会选择将其直接从网卡发出或者加入发送队列。

8)最终,软中断NET_TX_SOFTIRQ的处理程序会将发送队列里的包由网卡发出。

收包流程

1)网卡接收到一个数据包后,会向CPU发起一个硬件中断,该中断处理程序由网卡驱动实现。

2)中断上半部会为这个新来的数据包分配合适大小的skb,并将这个数据包从网卡的缓存中拷贝到内存。最后触发中断下半部继续处理。

3)网卡中断的下半部由软中断softirq实现,NET_RX_SOFTIRQ的处理程序将会被触发,这个处理程序会开始自底向上的协议栈处理。

4)网络层收到包后会先判断是否有原始套接字的监听,然后进入netfilter的NF_IP_PRE_ROUTEING hook点。
(libpcap等抓包程序一般都是使用SOCK_PACKET套接字实现,在NF_IP_PREROUTEING点之前就被获取了的。然而libpcap对收到的包只能监测不能修改,netfilter可以对其做生死判决)

5)进行路由判决,如果是目的是本机,进入netfilter的NF_IP_LOCAL_IN hook点,如果目的不是本地且需要对其进行转发,并进入netfilter的NF_IP_FORWARDING hook点。

6)目的为本机的包将继续向上传给传输层,如果是TCP包,将进行重组,并将数据存入socket的缓冲区。

7)此时如果有一个应用进程正在read这个socket或者阻塞在read这个socket上,将会将其唤醒并把缓冲区的数据从内核拷贝到用户态的buff里。read系统调用由此返回。

补充一点细节:
当进行大流量的网络通信的时候,发包软中断和收包软中断本身还可以重新触发自己以得到再次执行。
但是由于这样会导致用户态进程饥饿,于是作为改进,当大量软中断出现的时候,内核会唤醒内核线程ksoftirqd来处理这些负载。
发包中断和收包中断的处理程序有可能在在软中断触发执行的任何地方执行。包括中断返回时、网络子系统主动触发或者被ksoftirqd强制线程化。

Linux内核笔记--网络子系统初探的更多相关文章

  1. Linux内核笔记--内存管理之用户态进程内存分配

    内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...

  2. 【转载】linux内核笔记之进程地址空间

    原文:linux内核笔记之进程地址空间 进程的地址空间由允许进程使用的全部线性地址组成,在32位系统中为0~3GB,每个进程看到的线性地址集合是不同的. 内核通过线性区的资源(数据结构)来表示线性地址 ...

  3. 【转载】linux内核笔记之高端内存映射

    原文:linux内核笔记之高端内存映射 在32位的系统上,内核使用第3GB~第4GB的线性地址空间,共1GB大小.内核将其中的前896MB与物理内存的0~896MB进行直接映射,即线性映射,将剩余的1 ...

  4. Linux内核分析 - 网络[十四]:IP选项

    Linux内核分析 - 网络[十四]:IP选项 标签: linux内核网络structsocketdst 2012-04-25 17:14 5639人阅读 评论(1) 收藏 举报  分类: 内核协议栈 ...

  5. Linux内核中网络数据包的接收-第一部分 概念和框架

    与网络数据包的发送不同,网络收包是异步的的.由于你不确定谁会在什么时候突然发一个网络包给你.因此这个网络收包逻辑事实上包括两件事:1.数据包到来后的通知2.收到通知并从数据包中获取数据这两件事发生在协 ...

  6. Linux内核之网络

    应用层: 套接字将Unix一切都是内核的概念应用到网络连接中,内核跟用户空间套接字之间的接口实现在c的标准库中,使用了socketcall系统调用. socketcall充当了一个多路分解器,将各种任 ...

  7. Linux内核简介、子系统及分类

    一.内核简介 内核:在计算机科学中是一个用来管理软件发出的数据I/O(输入与输出)要求的计算机程序,将这些要求转译为数据处理的指令并交由中央处理器(CPU)及计算机中其他电子组件进行处理,是现代操作系 ...

  8. Linux内核内存管理子系统分析【转】

    本文转载自:http://blog.csdn.net/coding__madman/article/details/51298718 版权声明:本文为博主原创文章,未经博主允许不得转载. 还是那张熟悉 ...

  9. Linux内核之mmc子系统-sdio

    现在的Linux内核中,mmc不仅是一个驱动,而是一个子系统.这里通过分析Linux3.2.0内核,结合TI的arm335x平台及omap_hsmmcd host分析下mmc子系统,重点关注sdio及 ...

随机推荐

  1. my97中文乱码问题

    在使用my97日期插件后页面显示中文乱码问题: 解决方法: 把下面这段代码复盖到你的ZH-CN.js就解决了 var $lang={ errAlertMsg: "\u4E0D\u5408\u ...

  2. 关于数组去重的几种方法-------javascript描述

    第一种方法:借助json对象来实现,若json对象中无该属性则添加,否则不添加,最后返回json对象的属性,时间复杂度为O(n) function deleteArrayRepeat(arr) { v ...

  3. ThinkPHP3.2.3多文件上传,文件丢失问题的解决

    描述 thinkphp多文件上传时,有些时候会出现文件丢失的情况.比如上传多个图片,最终只上传了一个图片.本地测试的时候是正常的,但上传到服务器上就会出现丢失文件这种情况. 原因 查看tp上传类(Th ...

  4. PYTHON 写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者

    def a3(arg): ret = [ ] for i in range(len(arg)): if i % 2 == 1: ret.append(arg[i]) else: pass return ...

  5. SPOJ FTOUR2 - Free tour II

    Description 有些黑点,问你选择不超过 \(k\) 个黑点的路径,路径权值最大是多少. Sol 点分治. 这是qzc的论文题,不过我感觉他的翻译好强啊...我还是选择了自己去看题目... 点 ...

  6. 文件权限:普通(r、w、x)和特殊(s、t)

     linux中,常常涉及到权限的问题.文件的权限有3组,owner,group,other,每一组都有rwx三种设置.r(4):可读:w(2):可写:x(1):可执行.我们在执行shell命令ls - ...

  7. [MySQL] MySQL存储过程常用的函数

    一.字符串类 CHARSET(str) //返回字串字符集 CONCAT (string2  [,... ]) //连接字串 INSTR (string ,substring ) //返回substr ...

  8. IntelliJ IDEA WEB项目的部署配置

    以下内容是我网上找的比较全面了,其中关于facets配置很多地方都没有说明,其实很重要,我加入了自己的理解.其他来自网络.在导入一个项目有问题时,建议先创建一个正确的web项目,然后对比配置项,一般就 ...

  9. 【webGL】threejs常用的api

    /*** 场景(scene) ***/ var scene = new THREE.Scene(); // 创建场景 scene.add(x); // 插入场景 /*** 相机(camera) *** ...

  10. Linux kilin 安装和按键服务器步骤

    U盘启动,傻瓜式安装 设置root 密码 sudo passwd root vsftpd和ssh服务 使用apt-get可以直接安装vsftpd和ssh,首先要sudo apt-get update ...