Linux 网络栈剖析

合集下载

linux 内核协议栈丢包-解释说明

linux 内核协议栈丢包-解释说明

linux 内核协议栈丢包-概述说明以及解释1.引言1.1 概述Linux 内核协议栈作为网络通信的核心组成部分,在网络数据传输过程中扮演着至关重要的角色。

然而,随着网络流量的增加和网络环境的复杂化,出现丢包现象已经成为一种常见的问题,给网络通信质量以及数据传输的稳定性带来了不小的挑战。

本文将深入探讨Linux 内核协议栈丢包的问题,从丢包现象分析、常见原因及解决方法等方面展开探讨,希望通过对该问题的深入研究,能够为广大读者提供更加系统和全面的解决方案,以更好地应对日益复杂的网络环境与情况。

1.2 文章结构文章结构部分的内容应该涵盖本文的整体布局和组织架构,可以描述文章的章节设置和内容安排,让读者能够清晰地了解整篇文章的逻辑结构。

具体内容如下:文章结构部分将主要描述本文的整体架构和章节布局。

本文主要分为引言、正文和结论三个部分。

引言部分将概述本文的主题和目的,介绍Linux内核协议栈丢包问题的背景和重要性。

正文部分将详细介绍Linux 内核协议栈的简介,分析丢包现象的原因,以及常见的解决方法。

结论部分将对全文内容进行总结,并提出对策建议和展望未来的发展方向。

通过本文的结构安排,读者可以清晰地了解本文的逻辑脉络,帮助他们更好地理解和消化文章内容。

1.3 目的本文旨在探讨在使用Linux内核协议栈时可能出现的丢包现象及其原因,以及针对这些问题提出一些常见的解决方法。

通过对丢包现象进行分析和解决方案的讨论,旨在帮助读者更好地理解和解决在使用Linux系统中可能遇到的网络通信问题。

同时,也希望通过对这些问题的深入讨论,促进Linux内核协议栈的优化和改进,提升系统的稳定性和可靠性。

2.正文2.1 Linux 内核协议栈简介Linux内核协议栈是操作系统内核中的一个关键部分,负责网络数据包的接收、处理和发送。

它由多个层次构成,每个层次都有特定的功能,包括网络接口层、网络层、传输层和应用层。

在Linux系统中,协议栈的实现主要依赖于内核中的网络协议栈,其中包括传输层协议(如TCP和UDP)、网络层协议(如IP)和数据链路层协议(如Ethernet)。

linux内核堆栈解析方法

linux内核堆栈解析方法

在 Linux 系统中,内核堆栈(kernel stack)用于执行内核代码。

当发生操作系统内核崩溃、内核出现异常或需要调试时,理解和分析内核堆栈十分重要。

以下是分析 Linux 内核堆栈的常用方法:使用dmesg:当内核发生故障时,错误信息和堆栈追踪通常会输出到内核日志。

你可以使用 dmesg 命令查看内核日志中的堆栈追踪。

dmesg | grep -i stack操作系统崩溃时的系统日志:有时通过分析内核崩溃时的系统日志(如/var/log/syslog 或/var/log/messages、/var/log/kern.log)也可以找到有关堆栈信息。

使用 dump_stack() 函数:在内核代码中,你可以使用 dump_stack() 函数打印当前线程的堆栈信息。

这在调试内核代码时非常有用。

系统核心转储(Core Dump):内核崩溃时,操作系统有时会生成系统核心转储文件。

你可以使用 GNU Debugger(GDB)来分析内核转储文件。

首先,安装 Linux 的调试符号表(debugging symbols),然后使用 gdb 命令加载符号表和内核转储文件,最后使用 bt(backtrace)命令查看堆栈追踪。

gdb path/to/vmlinux path/to/core_dump(gdb) bt请注意,要使内核生成核心转储文件,需要正确配置内核。

具体配置方法取决于你所使用的 Linux 发行版。

内核调试器(如 KGDB 和 KDB):如果你正在研究内核问题,可以使用内核调试器 KGDB 或 KDB。

KGDB 是基于 GDB 的内核调试器,可以在源代码级别进行调试。

KDB 则是一个基于文本的内核调试器。

使用这些工具,你可以从内核级别设置断点、单步执行代码、检查内存内容和调用堆栈等。

通过以上方法可以帮助你分析 Linux 内核堆栈。

如何选择最佳方法取决于你的具体需求和问题。

在进行内核调试之前,请确保熟悉 Linux 操作系统和内核开发的基本知识。

linux协议栈

linux协议栈

linux协议栈Linux协议栈是Linux操作系统中网络通信的核心组件,也是实现网络通信的关键。

它基于TCP/IP协议栈,提供了一系列的网络协议和接口,负责数据在网络中的传输和接收。

Linux协议栈由多层协议组成,每层都有不同的功能和责任。

从底层到高层依次是链路层(Ethernet)、网络层(IP)、传输层(TCP/UDP)和应用层(HTTP/FTP等)。

每一层都有专门的协议来处理各自的任务,并通过各层之间的接口来传递数据。

在链路层,Linux协议栈使用网络接口卡(NIC)来将数据从计算机发送到网络,并从网络接收数据。

它负责将数据以数据帧的形式封装成网络包,并通过以太网协议(Ethernet)发送出去。

同时,它还负责接收数据帧,并将其解析成网络包交给上层协议处理。

在网络层,Linux协议栈使用IP协议来实现网络寻址和路由功能。

它负责将数据包从源地址发送到目标地址,同时还提供了一些其他的功能,如分片、重组和数据包的生存周期控制等等。

IP协议是整个互联网通信的基石,可以实现跨网络的通信。

在传输层,Linux协议栈提供了TCP和UDP两种协议来实现可靠传输和无连接传输。

TCP协议提供了可靠的、面向连接的数据传输,它通过采用滑动窗口、序号和确认机制来保证数据的可靠性。

而UDP协议则是一种无连接的传输协议,它只提供了数据传输的基本功能,不保证可靠性。

在应用层,Linux协议栈支持各种应用层协议,如HTTP、FTP、SMTP等,以满足不同的应用需求。

这些协议定义了应用程序与网络之间的通信规则和数据格式,让应用程序能够进行网络通信。

除了以上的四层协议,Linux协议栈还包括了其他的功能模块,如网络设备驱动、socket接口和网络管理等,它们共同协同工作,完成网络通信的任务。

总之,Linux协议栈是Linux操作系统中网络通信的核心组件,它提供了一系列的网络协议和接口,负责数据在网络中的传输和接收。

它基于TCP/IP协议栈,包括链路层、网络层、传输层和应用层等多层协议,以及其他的功能模块。

【IT专家】linux网络协议栈(四)链路层 (6)L2隧道(eoip)

【IT专家】linux网络协议栈(四)链路层 (6)L2隧道(eoip)

本文由我司收集整编,推荐下载,如有疑问,请与我司联系linux网络协议栈(四)链路层(6)L2隧道(eoip) 2014/01/13 4760 4.7、L2隧道(eoip):隧道,就是走捷径,使转发速度更快,L2隧道就是说高层报文在链路层即被转发了,而无需走高层协议栈再转发,比如这里要说的eoip(Ethernet over ip),就是说IP报文在以太网就被转发出去了。

 对于eoip,linux内核源码没有其实现,是raisecom根据开源代码实现的,在2.10代码树的rcios/eoip/目录下的eoip.c文件,下图是eoip在系统中的位置: 在eoip实现中,对eoip隧道的增删查改由用户应用程序和raisecom实现的netlink报文内核中控模块ctrlnetlink通讯实现,这里首先关注下eoip隧道的原理: 4.2.1、eoip隧道原理:下图是描述eoip隧道的结构体eoip_tunnel: list字段用于链接系统中所有的隧道; local_dev标识该隧道所在的接口,每一个eoip隧道都是建立在一个输入接口之上,在报文到达某一个接口时,首先就要判断该接口是否是一个隧道入口,判断方式就是遍历系统中所有隧道的接口是否是报文的输入接口(eoip_tunnel_lookup_local); remote_ip:这是eoip隧道的传输逻辑,比如已确定某报文需要通过某隧道传输,这时必须知道该报文从哪个接口转发出去,remote_ip就是用于确定出接口,制造一个“传输层协议为eoip、目的IP为remote_ip”的路由表匹配项,再查路由表(ip_route_output_key),查到的路由结果指示的出接口就是转发该报文的出接口;由此也可见,用户在创建一个eoip隧道后,还需要创建一个相应的路由条目; tunnelID:系统中每个eoip隧道的id; isbackup+ masterlinkstatus:这两个字段的确切含义还不很清除,但它们共同决定了某一隧道当前是否使能:在((isbackup == 0) || (isbackup == 1 masterlinkstatus = 0))的条件下,该隧道是使能的,即在(isbackup == 1 masterlinkstatus = 1)情况下该隧道。

linux,ip协议栈,虚拟网络接口

linux,ip协议栈,虚拟网络接口

竭诚为您提供优质文档/双击可除linux,ip协议栈,虚拟网络接口篇一:linux虚拟网桥linux内核是通过一个虚拟的网桥设备来实现桥接的。

这个虚拟设备可以绑定若干个以太网接口设备,从而将它们桥接起来。

如下图(摘自ulni):网桥设备br0绑定了eth0和eth1。

对于网络协议栈的上层来说,只看得到br0,因为桥接是在数据链路层实现的,上层不需要关心桥接的细节。

于是协议栈上层需要发送的报文被送到br0,网桥设备的处理代码再来判断报文该被转发到eth0或是eth1,或者两者皆是;反过来,从eth0或从eth1接收到的报文被提交给网桥的处理代码,在这里会判断报文该转发、丢弃、或提交到协议栈上层。

而有时候eth0、eth1也可能会作为报文的源地址或目的地址,直接参与报文的发送与接收(从而绕过网桥)。

网桥的配置在linux里面使用网桥非常简单,仅需要做两件事情就可以配置了。

其一是在编译内核里把conFig_bRidge或condig_bRidge_module编译选项打开;其二是安装brctl工具。

第一步是使内核协议栈支持网桥,第二步是安装用户空间工具,通过一系列的ioctl(linux,ip协议栈,虚拟网络接口)调用来配置网桥。

下面以一个相对简单的实例来贯穿全文,以便分析代码。

linux机器有4个网卡,分别是eth0~eth4,其中eth0用于连接外网,而eth1,eth2,eth3都连接到一台pc机,用于配置网桥。

只需要用下面的命令就可以完成网桥的配置:brctladdbrbr0(建立一个网桥br0,同时在linux内核里面创建虚拟网卡br0)brctladdifbr0eth1brctladdifbr0eth2brctladdifbr0eth3(分别为网桥br0添加接口eth1,eth2和eth3)其中br0作为一个网桥,同时也是虚拟的网络设备,它即可以用作网桥的管理端口,也可作为网桥所连接局域网的网关,具体情况视你的需求而定。

学习嵌入式linux内核网络栈代码的准备知识(1)

学习嵌入式linux内核网络栈代码的准备知识(1)


千锋3G嵌入式移动互联网技术研发培训中心 千锋3G嵌入式移动互联网技术研发培训中心 3G
IP层:处理网络层的操作,网络层用struct packet_type结构表示。文件主要有: /net/ipv4/ip_forward.c ip_fragment.c ip_input.c ip_output.c etc. 学习嵌入式之数据链路层和驱动程序:每个网络设备以 struct net_device表示,通用的处理在dev.c中,驱动程序 都在/driver/net目 录下。 2. 两台主机建立udp通信所走过的函数列表 ^ | sys_read fs/read_write.c | sock_read net/socket.c | sock_recvmsg net/socket.c | inet_recvmsg net/ipv4/af_inet.c
比如在inetstreamops里有个inetrelease的操作这个操作除了释放socket的类型空间操作外还通过调用socket连接的sock的close操作对于stream类型来说即tcpclose来关闭sockwwwembedtrainorgwwwmobiletrainorg3g嵌入式移动互联网技术研发培训中心创建socket同时还创建sock数据空间初始化sock初始化过程主要做的事情是初始化三个队列receivequeue接收到的数据包skbuff链表队列sendqueu需要发送数据包的skbuff链表队列backlogqueue主要用于tcp中三次握手成功的那些数据包自己猜的根据familytype参数初始化sock的操作比如对于family为inet类型的type为stream类型的sockproto初始化为tcpprot

千锋3G嵌入式移动互联网技术研发培训中心 千锋3G嵌入式移动互联网技术研发培训中心 3G

深度剖析Linux0.11系统中堆栈的使用方法

在工作中关于Linux系统中的堆栈问题一直是工程师们很头疼的问题,尤其出现一些新的版本,下面就与大家一起分享以下Linux0.11 系统中堆栈的使用方法。

一、系统引导初始化临时使用的堆栈。

二、进入保护模式后提供内核程序始化使用的堆栈,该堆栈也是后来任务0使用的用户态堆栈。

三、每个任务通过系统调用,执行内核程序时使用的堆栈,称之为任务的内核态堆栈,每个任务都有自己独立的内核态堆栈。

四、任务在用户态执行的堆栈,位于任务(进程)逻辑地址空间近末端处。

使用多个栈或在不同情况下使用不同栈的主要原因首先,由于从实模式进入保护模式,使得CPU对内存寻址访问方式发生了变化,因此需要重新设置堆栈区域;其次,为了解决不同CPU特权级共享使用堆栈带来的保护问题,执行0级的内核代码和执行3级的用户代码需要使用不同的栈。

当一个任务进入内核态运行时,就会使用其TSS段中给出的特权级0的堆栈指针tss.ss0.tss.esp0,即内核栈,原用户栈指针会保存在内核栈中,而当从内核态返回用户态时,就会恢复使用用户态的堆栈。

以下分别说明。

开机初始化时(bootsect.s,setup.s)当bootsect代码被ROM BIOS引导加载到物理内存0x7c00处时,并没有设置堆栈段,程序也没有使用堆栈,直到bootsect被移动到0x9000:0处时,才把堆栈段寄存器SS设置为0x9000,堆栈指针esp寄存器设置为0xff00,所以堆栈堆栈在0x9000:0xff00处(boot/bootsect.s L61,62)setup.s也使用这个堆栈进入保护模式时候(head.s,L31)此时堆栈段被设置为内核数据段(0x10),堆栈指针esp设置成指向user_stack数组(sched.c L67~72)的顶端,保留了1页内存作为堆栈使用。

初始化时(main.c)在执行move_to_user_mode()代码把控制权移交给任务0之前,系统一直使用上述堆栈,而在执行过move_to_user_mode()之后,main.c的代码被“切换”成任务0中执行。

Linux操作系统中的网络通信原理

Linux操作系统中的网络通信原理一、引言Linux操作系统是一种广泛应用于各种领域的开源操作系统,而网络通信则是其最重要的功能之一。

本文将深入探讨Linux操作系统中的网络通信原理,包括网络协议、套接字编程以及网络通信的实现机制等方面。

二、网络协议1. TCP/IP协议栈TCP/IP协议栈是Linux操作系统中实现网络通信的基础。

它由四个层次组成:网络接口层、网络层、传输层和应用层。

网络接口层负责将数据从应用层传输到网络层,网络层负责将数据从源主机传输到目标主机,传输层负责提供可靠的数据传输服务,而应用层则负责处理具体的网络应用。

2. IP地址和端口号IP地址是在Internet上对主机和路由器进行唯一标识的地址,而端口号则用于标识网络中的不同进程或服务。

Linux操作系统中使用IP 地址和端口号来实现网络通信的目的。

3. ICMP协议ICMP协议是Internet控制报文协议的缩写,用于在IP网络中发送控制消息和错误报文。

它有助于网络中的主机和路由器之间进行通信和故障排除。

三、套接字编程套接字是实现网络通信的一种机制,也是Linux操作系统中网络通信的核心。

通过套接字编程,可以在应用层使用socket函数进行网络通信的建立和数据传输。

1. 套接字类型在Linux操作系统中,套接字类型可以分为面向连接的套接字和无连接的套接字。

面向连接的套接字主要基于TCP协议,提供可靠的数据传输和连接管理功能;无连接的套接字则主要基于UDP协议,提供高效的数据传输和较低的开销。

2. 套接字编程流程套接字编程的一般流程包括创建套接字、绑定地址、监听连接、接受连接、数据传输和关闭套接字等步骤。

通过这些步骤,应用程序可以实现与其他主机或服务的通信。

四、网络通信实现机制1. 数据链路层数据链路层是网络通信中的第一层,主要负责将数据包从物理层传输到网络层。

在Linux操作系统中,数据链路层由网络接口卡驱动程序和相应的设备驱动程序实现。

Linux系统常见的网络连接问题及解决方案详解

Linux系统常见的网络连接问题及解决方案详解在使用Linux系统过程中,我们经常会遇到各种网络连接问题。

本文将详细介绍几种常见的网络连接问题,并提供相应的解决方案。

一、无法连接到网络无法连接到网络是最常见的网络问题之一。

当我们无法连接到网络时,首先需要确认以下几点:1. 网络连接是否正常:检查网络连接是否已启用,确保网络线缆连接到正确的接口上。

2. IP地址是否配置正确:通过 ifconfig 命令检查当前网络接口的IP地址和子网掩码是否配置正确。

3. DNS解析是否正常:配置 DNS 服务器的地址,可通过编辑/etc/resolv.conf 文件来指定 DNS 服务器地址。

若以上检查都正常,而仍无法连接到网络,则可能有以下原因导致:1. 防火墙配置问题:检查防火墙是否阻止了网络连接。

可以使用iptables 命令来查看、修改防火墙规则。

2. 硬件问题:检查网卡是否正常工作,可以通过 lspci 命令查看系统中是否存在网卡设备。

3. 路由器配置问题:检查路由器的配置,确保网络设置正确。

二、网络延迟高网络延迟高会导致网络连接变慢或不稳定。

以下是一些降低网络延迟的解决方案:1. 检查网络带宽:使用网速测试工具(如speedtest-cli)检查当前网络带宽情况。

如果带宽使用率过高,可以考虑限制某些应用程序的带宽使用。

2. 优化网络设置:调整系统的TCP参数,可以使用 sysctl 命令来修改。

例如,通过增加tcp_fin_timeout 值来减少关闭连接时的等待时间。

3. 检查网络设备:检查路由器、交换机等网络设备是否正常工作。

可以尝试重新启动这些设备,或升级其固件。

三、无法解析域名无法解析域名是指无法通过域名获取相应的IP地址。

解决这个问题可以从以下几个方面入手:1. 检查DNS配置:查看 /etc/resolv.conf 文件,确认已正确配置DNS 服务器的地址。

也可以尝试更换为其他的DNS服务器地址,如Google DNS(8.8.8.8)。

linux下tcp-ip栈和Netfilter的分析编程

NetFilter架构流程一个数据包按照如下图所示的过程通过Netfilter系统:--->[1]--->[ROUTE]--->[3]--->[4]--->| ^| |local || [ROUTE]v |[2] [5]| ^| |v |从图中可以看到IPv4一共有5个钩子函数,分别为:1 NF_IP_PRE_ROUTING2 NF_IP_LOCAL_IN3 NF_IP_FORWARD4 NF_IP_POST_ROUTING5 NF_IP_LOCAL_OUT数据报从左边进入系统,进行IP校验以后,数据报经过第一个钩子函数NF_IP_PRE_ROUTING[1]进行处理;然后就进入路由代码,其决定该数据包是需要转发还是发给本机的;若该数据包是发被本机的,则该数据经过钩子函数NF_IP_LOCAL_IN[2]处理以后然后传递给上层协议;若该数据包应该被转发则它被NF_IP_FORWARD[3]处理;经过转发的数据报经过最后一个钩子函数NF_IP_POST_ ROUTING[4]处理以后,再传输到网络上。

本地产生的数据经过钩子函数NF_IP_LOCAL_OUT [5]处理可以后,进行路由选择处理,然后经过NF_IP_POST_ROUTING[4]处理以后发送到网络上。

内核模块可以对一个或多个这样的钩子函数进行注册挂接,并且在数据报经过这些钩子函数时被调用,从而模块可以修改这些数据报,并向netfilter返回如下值:NF_ACCEPT 继续正常传输数据报NF_DROP 丢弃该数据报,不再传输NF_STOLEN 模块接管该数据报,不要继续传输该数据报NF_QUEUE 对该数据报进行排队(通常用于将数据报给用户空间的进程进行处理)NF_REPEAT 再次调用该钩子函数内核模块可以注册一个新的规则表(table),并要求数据报流经指定的规则表。

这种数据报选择用于实现数据报过滤(filter表),网络地址转换(Nat表)及数据报处理(mangle表)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

简介:Linux®操作系统的最大特性之一就是它的网络栈。

它最初源于BSD 的网络栈,具有一套非常干净的接口,组织得非常好。

其接口范围从协议无关层(例如通用socket 层接口或设备层)到各种网络协议的具体层。

本文将从分层角度对 Linux 网络栈的接口进行探索,并介绍其中的一些主要结构。

协议简介虽然对于网络的正式介绍一般都参考了 OSI(Open Systems Interconnection)模型,但是本文对 Linux 中基本网络栈的介绍分为四层的 Internet 模型(如图 1 所示)。

图 1. 网络栈的 Internet 模型这个栈的最底部是链路层。

链路层是指提供对物理层访问的设备驱动程序,这可以是各种介质,例如串口链路或以太网设备。

链路层上面是网络层,它负责将报文定向到目标位置。

再上一层称为传输层,负责端到端的通信(例如,在一台主机内部)。

尽管网络层负责管理主机之间的通信,但是传输层需要负责管理主机内部各端之间的通信。

最后一层是应用层,它通常是一个语义层,能够理解要传输的数据。

例如,超文本传输协议(HTTP)就负责传输服务器和客户机之间对 Web 内容的请求与响应。

实际来说,网络栈的各个层次有一些更为人所熟知的名字。

在链路层上,可以找到以太网,这是最常用的一种高速介质。

更早的链路层协议包括一些串口协议,例如 SLIP(Serial Line Internet Protocol)、CSLIP(Compressed SLIP)和PPP(Point-to-Point Protocol)。

最常见的网络层协议是 IP(Internet Protocol),但是网络层中还存在一些满足其他需求的协议,例如ICMP(Internet Control Message Protocol)和ARP( Address Resolution Protocol)。

在传输层上是 TCP(Transmission Control Protocol)和 UDP (User Datagram Protocol)。

最后,应用层中包含很多大家都非常熟悉的协议,包括标准的 Web 协议 HTTP 和电子邮件协议 SMTP(Simple Mail Transfer Protocol)。

回页首核心网络架构现在继续了解 Linux 网络栈的架构以及如何实现这种 Internet 模型。

图 2 提供了 Linux 网络栈的高级视图。

最上面是用户空间层,或称为应用层,其中定义了网络栈的用户。

底部是物理设备,提供了对网络的连接能力(串口或诸如以太网之类的高速网络)。

中间是内核空间,即网络子系统,也是本文介绍的重点。

流经网络栈内部的是 socket 缓冲区(sk_buffs),它负责在源和汇点之间传递报文数据。

您很快就将看到 sk_buff 的结构。

图 2. Linux 高级网络栈架构首先,让我们来快速浏览一下 Linux 网络子系统的核心元素,后续章节中会更详细进行介绍。

顶部(请参阅图 2)是系统调用接口。

它简单地为用户空间的应用程序提供了一种访问内核网络子系统的方法。

位于其下面的是一个协议无关层,它提供了一种通用方法来使用底层传输层协议。

然后是实际协议,在回页首网络协议网络协议这一节对一些可用的特定网络协议作出了定义(例如 TCP、UDP 等)。

它们都是在 linux/net/ipv4/af_inet.c 文件中一个名为 inet_init 的函数中进行初始化的(因为 TCP 和 UDP 都是 inet 簇协议的一部分)。

inet_init函数使用 proto_register 函数来注册每个内嵌协议。

这个函数是在linux/net/core/sock.c 中定义的,除了可以将这个协议添加到活动协议列表中之外,如果需要,该函数还可以选择分配一到多个 slab 缓存。

通过 linux/net/ipv4/ 目录中 udp.c 和 raw.c 文件中的 proto 接口,您可以了解各个协议是如何标识自己的。

这些协议接口每个都按照类型和协议映射到 inetsw_array,该数组将内嵌协议与操作映射到一起。

inetsw_array 结构及其关系如图 3 所示。

最初,会调用 inet_init 中的inet_register_protosw 将这个数组中的每个协议都初始化为 inetsw。

函数inet_init 也会对各个 inet 模块进行初始化,例如 ARP、ICMP 和 IP 模块,以及 TCP 和 UDP 模块。

图 3. Internet 协议数组结构Socket 协议的相互关系回想以下在创建 socket 时,需要指定类型和协议,例如my_sock =socket( AF_INET, SOCK_STREAM, 0 )。

AF_INET 表示一个 Internet 地址簇,它使用的是一个流 socket,定义为 SOCK_STREAM(如此处的 inetsw_array 所示)。

注意在图 3中,proto 结构定义了传输特有的方法,而 proto_ops 结构则定义了通用的 socket 方法。

可以通过调用 inet_register_protosw 将其他协议加入到 inetsw 协议中。

例如,SCTP 就是通过调用linux/net/sctp/protocol.c 中的 sctp_init 加入其中的。

有关 SCTP 的更多信息,请参阅参考资料一节的内容。

socket 中的数据移动是使用一个所谓的 socket 缓冲区(sk_buff)的核心结构实现的。

sk_buff 中包含了报文数据,以及涉及协议栈中多个层次的状态数据。

所发送或接收的每个报文都是使用一个 sk_buff 表示的。

sk_buff 结构是在 linux/include/linux/skbuff.h 中定义的,如图 4 所示。

图 4. Socket 缓冲区及其与其他结构的关系如图所示,多个 sk_buff 可以针对某个给定连接链接在一起。

每个 sk_buff都在设备结构(net_device)中标识报文发送的目的地,或者接收报文的来源地。

由于每个报文都是使用一个 sk_buff 表示的,因此报文头都可以通过一组指针(th、iph 和 mac[用于 Media Access Control 或者 MAC 头])方便地进行定位。

由于 sk_buff 是 socket 数据管理的中心,因此创建了很多支持函数来对它们进行管理。

其中有些函数用于创建和销毁 sk_buff 结构,或对它进行克隆或排队管理。

针对给定的 socket,Socket 缓冲区可以链接在一起,这样可以包含众多信息,包括到协议头的链接、时间戳(报文是何时发送或接收的),以及与这个报文相关的设备。

回页首设备无关接口协议层下面是另外一个无关接口层,它将协议与具有很多各种不同功能的硬件设备连接在一起。

这一层提供了一组通用函数供底层网络设备驱动程序使用,让它们可以对高层协议栈进行操作。

首先,设备驱动程序可能会通过调用 register_netdevice 或unregister_netdevice 在内核中进行注册或注销。

调用者首先填写net_device 结构,然后传递这个结构进行注册。

内核调用它的 init 函数(如果定义了这种函数),然后执行一组健全性检查,并创建一个 sysfs 条目,然后将新设备添加到设备列表中(内核中的活动设备链表)。

在linux/include/linux/netdevice.h 中可以找到这个 net_device 结构。

这些函数都是在 linux/net/core/dev.c 中实现的。

要从协议层向设备中发送 sk_buff,就需要使用 dev_queue_xmit 函数。

这个函数可以对 sk_buff 进行排队,从而由底层设备驱动程序进行最终传输(使用sk_buff 中引用的 net_device 或 sk_buff->dev 所定义的网络设备)。

dev 结构中包含了一个名为 hard_start_xmit 的方法,其中保存有发起 sk_buff 传输所使用的驱动程序函数。

报文的接收通常是使用 netif_rx 执行的。

当底层设备驱动程序接收一个报文(包含在所分配的 sk_buff 中)时,就会通过调用 netif_rx 将 sk_buff 上传至网络层。

然后,这个函数通过 netif_rx_schedule 将 sk_buff 在上层协议队列中进行排队,供以后进行处理。

可以在 linux/net/core/dev.c 中找到dev_queue_xmit 和 netif_rx 函数。

最近,内核中引入了一种新的应用程序编程接口(NAPI),该接口允许驱动程序与设备无关层(dev)进行交互。

有些驱动程序使用的是 NAPI,但是大多数驱动程序仍然在使用老式的帧接收接口(比例大约是 6 比 1)。

NAPI 在高负载的情况下可以产生更好的性能,它避免了为每个传入的帧都产生中断。

回页首设备驱动程序网络栈底部是负责管理物理网络设备的设备驱动程序。

例如,包串口使用的SLIP 驱动程序以及以太网设备使用的以太网驱动程序都是这一层的设备。

在进行初始化时,设备驱动程序会分配一个 net_device 结构,然后使用必须的程序对其进行初始化。

这些程序中有一个是 dev->hard_start_xmit,它定义了上层应该如何对 sk_buff 排队进行传输。

这个程序的参数为 sk_buff。

这个函数的操作取决于底层硬件,但是通常 sk_buff 所描述的报文都会被移动到硬件环或队列中。

就像是设备无关层中所描述的一样,对于 NAPI 兼容的网络驱动程序来说,帧的接收使用了 netif_rx 和 netif_receive_skb 接口。

NAPI 驱动程序会对底层硬件的能力进行一些限制。

有关更详细的信息,请参阅参考资料一节的内容。

∙您可以参阅本文在 developerWorks 全球站点上的英文原文。

∙请查阅 上的“Introduction to the Internet Protocols”,获得有关 TCP/IP、UDP 和 ICMP 的简要介绍。

∙“使用 Linux 系统调用的内核命令”(developerWorks,2007 年 3 月)介绍了 Linux 系统调用接口,它是 Linux 内核中很重要的一层,GNU C Library(glbic)提供了对用户空间支持,这样便可以在用户空间和内核之间进行函数调用。

∙“使用 /proc 文件系统来访问 Linux 内核的内容”(developerWorks,2006 年 3 月)介绍了 /proc 文件系统,它是一个虚拟文件系统,为用户空间的应用程序与内核进行通信提供了一种创新的方法。

相关文档
最新文档