Linux内核网络部分分析.ppt

上传人:小飞机 文档编号:5437938 上传时间:2023-07-07 格式:PPT 页数:34 大小:281.49KB
返回 下载 相关 举报
Linux内核网络部分分析.ppt_第1页
第1页 / 共34页
Linux内核网络部分分析.ppt_第2页
第2页 / 共34页
Linux内核网络部分分析.ppt_第3页
第3页 / 共34页
Linux内核网络部分分析.ppt_第4页
第4页 / 共34页
Linux内核网络部分分析.ppt_第5页
第5页 / 共34页
点击查看更多>>
资源描述

《Linux内核网络部分分析.ppt》由会员分享,可在线阅读,更多相关《Linux内核网络部分分析.ppt(34页珍藏版)》请在三一办公上搜索。

1、第8章 Linux内核网络部分实现分析,本章将以面向对象的思想为核心,分别对网络部分的4个主要对象:协议、套接字、套接字缓冲区及网络设备接口进行分析。,概述,网络部分的设计思想(1)Linux的网络部分沿用了传统的层次结构,用户进程,套接字,网络协议,网络设备,(2)Linux对以上网络层次的实现采用了面向对象的设计方法,层次模型中的各个层次被抽象为对象。网络协议(protocol):是一种语言,它规定了通信双方之间交换信息的一种规范,是网络传输的基础。套接字(Socket):一个套接字就是网络中的一个连接,它向用户提供了文件的I/O,并和网络协议紧密地联系在一起,体现了网络和文件系统、进程管

2、理之间的关系,它是网络传输的入口。设备接口(deviceandinterface):网络设备接口控制着网络数据由软件硬件软件的过程,体现了网络和设备的关系,它是网络传输的桥梁。套接字缓冲区(sh_buff):网络中的缓冲器叫做套接字缓冲区,它是一块保存网络数据的内存区域,体现了网络和内存管理之间的关系,它是网络传输的灵魂。,4个对象之间的关系:,套接字,网络协议,套接字缓冲区,设备接口,网络协议,网络参考模型OSI参考模型和TCP/IP参考模型,TCP/IP工作原理及数据流TCP/IP协议集,Internet协议(IP)IP定义了一个协议,而不是连接。IP主要负责数据报在计算机之间的寻址问题,

3、并管理这些数据报的分段过程。IP负责数据报的路由,决定数据报发送到哪里以及出现问题时更换路由。IP数据报头,套接字,套接字,TCP/IP内的数据流,输出,用户,输入,以太网,网络接口,IP输入队列,TCP是传输层使用最为广泛的一协议,它可以向上层提供面向连接的协议,使上层启动应用程序,以确保网络上所发送的数据报被完整接收。TCP必须与低层的IP(使用IP定义好的方法)和高层的应用程序进行通信,套接字(Socket),套接字在网络中的作用和地位Socket在所有的网络操作系统中都是必不可少的,而且在所有的网络应用程序中也是必不可少的。,套接字,套接字,套接字接口的种类Linux所支持套接字地址族

4、如下:UNIX Unix域套接字INET 使用TCP/IP的因特网地址族AX25 业余无线X25IPX IPXAPPLETALK APPLETALKX25 X25,Linux BSD支持的套接字类型:Stream 提供可靠的面向连接传输的数据流,保证数据传输过程中无丢失、无损坏和无冗余。I N E T地址族中的T C P协议支持该套接字。Datagram 提供数据的双向传输,但不保证消息(message)的准确到达,即使消息能够到达,也无法保证其顺序性,并可能有冗余或损坏。I N E T地址族中的U D P协议支持该套接字。Raw 是低于传输层的低级协议或物理网络提供的套接字类型,比如通过分析

5、为以太网设备所创建的R a w套接字,可看到裸I P数据流。Reliable Delivered Messages 类似于Datagram套接字,但它可以保证数据的正确到达。Sequenced Packets 类似于Stream套接字,但它的报文大小是可变的。Packet 这是Linux对标准BSD套接字类型的扩展,它允许应用程序在设备层直接访问报文数据。,套接字的工作原理 INET和BSD套接字之间的接口通过Internet地址族套接字操作集实现,这些操作集实际是一组协议的操作例程,在include/linux/net.h中定义为proto_ops:,struct proto_ops int

6、 family;int(*release)(struct socket*sock)int(*bind)(struct socket*sock,struct sockaddr*umyaddr,int sockaddr_len)int(*connect)(.).int(*accept)(.)int(*listen)(),BSD套接字层通过调用proto_ops结构中的相应函数执行任务BSD套接字层向INET套接字层传递socket数据结构来代表一个BSD套接字,socket数据机构在include/linux/net.h中定义如下:struct socketsocket_state state;u

7、nsigned long flags;struct proto_ops*ops;struct inode*inode;struct fasync_struct*fasync_list;struct file*file;.,在INET套接字层,它利用自己的sock数据结构来代表该套接字,因此,这两个结构之间存在着链接关系,sock结构定义于include/net/sock.h在BSD的socket数据结构中存在一个指向sock的指针sk,而在sock中又有一个指向socket的指针,这两个指针将BSD socket数据结构和sock数据结构链接起来。BSD套接字上的详细操作与具体的底层地址族有关

8、,底层地址族的不同实际意味着寻址方式、采用的协议等的不同内核负责在BSD套接字和底层的地址族之间建立联系。在内核中,地址族和协议信息保存在inet_protos向量中,其定义于include/net/protocol.h:,struct inet_protocol*inet_protosMAX_INET_PROTOS;/*This is used to register protocols*/struct inet_protocol int(*handler)(struct sk_buff*skb);void(*err_handler)(struct sk_buff*skb,u32 info)

9、;struct inet_protocol*next;unsigned char protocol;unsigned char copy:1;void*data;const char*name;,套接字缓冲区(sk_buff),Linux利用套接字缓冲区在协议层和网络设备之间传送数据。sk_buff包含了一些指针和长度信息,从而可让协议层以标准的函数或方法对应用程序的数据进行处理。,每个sk_buff均包含一个数据块、四个数据指针以及两个长度字段。利用四个数据指针,各协议层可操纵和管理套接字缓冲区的数据,这四个指针的用途如下:,Head:指向内存中数据区的起始地址。sk_buff和相关数据块在

10、分配之后,该指针的值是固定的。Data:指向协议数据的当前起始地址。该指针的值随当前拥有sk_buff的协议层的变化而变化。Tail:指向协议数据的当前结尾地址。和data指针一样,该指针的值也随当前拥有sk_buff的协议层的变化而变化。End:指向内存中数据区的结尾。和head指针一样,sk_buff被分配之后,该指针的值也固定不变。sk_buff的两个长度字段,len和truesize,分别描述当前协议数据报的长度和数据缓冲区的实际长度。,sk_buff 定义于include/linux/skbuff.h中:struct sk_buff struct sk_buff*next;struc

11、t sk_buff*prev;struct sk_buff_head*list;struct sock*sk;struct timevalstamp;struct net_device*dev;unionstruct tcphdr*th;struct udphdr*uh;struct icmphdr*icmph;struct igmphdr*igmph;struct iphdr*ipiph;struct spxhdr*spxh;unsigned char*raw;h;,unionstruct iphdr*iph;struct ipv6hdr*ipv6h;struct arphdr*arph;s

12、truct ipxhdr*ipxh;unsigned char*raw;nh;union struct ethhdr*ethernet;unsigned char*raw;mac;struct dst_entry*dst;charcb48;,unsigned int len;unsigned int data_len;unsigned intcsum;unsigned char _unused,cloned,pkt_type,ip_summed;_u32priority;atomic_tusers;unsigned shortprotocol;unsigned shortsecurity;un

13、signed inttruesize;unsigned char*head;unsigned char*data;unsigned char*tail;unsigned char*end;void(*destructor)(struct sk_buff*);,网络设备接口 驱动程序部分 网络设备接口核心部分,Linux网络设备接口的适用面很广,所有的Linux网络设备都遵循同样的接口,它提供了丰富的接口功能,但是每一个设备并不是完全都要用到这些功能。在源代码中,用一种具有一系列操作方法的数据结构来描述网络设备,这样做的目的是为了在C语言中引入C+面向对象的思想。,物理层上有许多不同类型的网络接

14、口设备,在文件include/linux/if_arp.h的28行里定义了ARP能处理的各种的物理设备的标志符。网络设备接口要负责具体物理介质的控制,从物理介质接收以及发送数据,并对物理介质进行诸如最大数据包之类的各种设置。这里我们以比较简单的3Com3c501 太网卡的驱动程序为例,大概讲一下这层的工作原理。源码在Linux/drivers/net/3c501.c。,一个网卡当然最主要的是完成数据的接收和发送发送相对来说比较简单,在Linux/drivers/net/3c501.c的行475 开始的el_start_xmit()这个函数就是实际向3Com3c501以太网卡发送数据的函数,具体

15、的发送工作不外乎是对一些寄存器的读写,源码的注释很清楚,大家可以看看。,接收的工作相对来说比较复杂。通常来说,一个新的包到了,或者一个包发送完成了,都会产生一个中断。Linux/drivers/net/3c501.c的572开始el_interrupt()的函数里面,前半部份处理的是包发送完以后的汇报,后半部份处理的是一个新的包来的,就是说接收到了新的数据。el_interrupt()函数并没有对新的包进行太多的处理,就交给了接收处理函数el_receive()。el_receive()首先检查接收的包是否正确,如果是一个“好”包就会为包分配一个缓冲结构(dev_alloc_skb(),这样驱

16、动程序对包的接收工作就完成了,通过调用上层的函数netif_rx()(net/core/dev.c1214行),把包交给上层。,驱动程序怎么样和上层建立联系呢?就是说接收到包以后怎么送给上层,以及上层怎么能调用驱动程序的发送函数呢?由下往上的关系,是通过驱动程序调用上层的netif_rx()(net/core/dev.c 1214行)函数实现的,驱动程序通过这个函数把接到的数据交给上层,请注意所有的网卡驱动程序都需要调用这个函数的,这是网络接口核心层和网络接口设备联系的桥梁。,由上往下的关系就复杂点。网络接口核心层需要知道有多少网络设备可以用,每个设备的函数的入口地址等都要知道。指针struc

17、tnet_device*dev_base(Linux/include/linux/netdevice.h 436行)就是保存了网络接口核心层所知道的所有设备。对于网络接口核心层来说,所有的设备都是一个net_device结构,它在include/linux/netdevice.h,line 233里被定义,这是从网络接口核心层的角度看到的一个抽象的设备,我们来看看网络接口核心层的角度看到的网络设备具有的功能:,struct net_device open()stop()hard_start_xmit()hard_header()rebuild_header()set_mac_address()

18、do_ioctl()set_config()hard_header_cache()header_cache_update()change_mtu()tx_timeout()hard_header_parse()neigh_setup()accept_fastpath(),如果网络接口核心层需要由下层发送数据的时候,在dev_base找到设备以后,就直接调dev-hard_start_xmit()的这个函数来让下层发数据包。,驱动程序要让网络接口核心层知道自己的存在,当然要加入dev_base所指向的指针链,然后把自己的函数以及各种参数和net_device里的相应的域对应起来。加入dev_ba

19、se所指向的指针链是通过函数register_netdev(&dev_3c50)(linux/drivers/net/net_init.c,line 532)建立的。而把自己的函数以和net_device里的相应的域及各种参数关系的建立是在el1_probe1()(Linux/drivers/net/3c501.c)里进行的:,el1_probe1()dev-open=,网络接口核心层的上层是具体的网络协议,下层是驱动程序,我们以及解决了下层的关系,但和上层的关系没有解决。先来讨论一下网络接口核心层和网络协议族部份的关系,这种关系不外乎也是接收和发送的关系。网络协议,例如IP,ARP等的协议要

20、发送数据包的时候会把数据包传递给这层,那么这种传递是通过什么函数来发生的呢?网络接口核心层通过dev_queue_xmit()(net/core/dev.c,line975)这个函数向上层提供统一的发送接口,也就是说无论是IP,还是ARP协议,通过这个函数把要发送的数据传递给这一层,想发送数据的时候就调用这个函数就可以了。dev_queue_xmit()做的工作最后会落实到dev-hard_start_xmit(),而dev-hard_start_xmit()会调用实际的驱动程序来完成发送的任务。,和上层网络协议层的关系是通过static struct packet_ptype_base16(net/core/dev.c line 164)这个数组解决的。这个数组包含了需要接收数据包的协议,以及它们的接收函数的入口。如:IP协议接收数据是通过ip_rcv()函数的,而ARP协议是通过arp_rcv()的,网络接口核心层只要通过这个数组就可以把数据交给上层函数了。如果有协议想把自己添加到这个数组,是通过dev_add_pack()(net/core/dev.c,line233)函数,从数组删除是通过dev_remove_pack()函数的。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号