linux网络体系架构

原创kylin_zeng:http://blog.csdn.net/kylin_fire_zeng  本文参考国嵌视频教程,再此感谢国嵌教育。

一、协议栈层次对比:


1)网络接口层把数据链路层和物理层合并在了一起,提供访问物理设备的驱动程序,对应的网络协议主要是以太网协议。
2)网络层协议管理离散的计算机间的数据传输,如IP协议为用户和远程计算机提供了信息包的传输方法,确保信息包能正确地到达目的机器。重要的网络层协议包括ARP(地址解析协议)、ICMP(Internet控制消息协议)和IP协议(网际协议)等
3)传输层的功能包括:格式化信息流、提供可靠传输。传输层包括TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协议),它们是传输层中最主要的协议
4)应用层位于协议栈的顶端,它的主要任务是服务于应用,如利用FTP(文件传输协议)传输一个文件。常见的应用层协议有:HTTP,FTP,Telnet等。应用层是Linux网络设定很关键的一层,Linux服务器的配置文档主要针对应用层中的协议


二、linux网络子系统
1)

2)Linux 网络子系统的顶部是系统调用接口层。它为用户空间的应用程序提供了一种访问内核网络子系
统的方法。位于其下面的是一个协议无关层,它提供了一种通用方法来使用传输层协议。然后是具体
协议的实现,在Linux 中包括内嵌的协议TCP、UDP,当然还有IP。然后是设备无关层,它提供了
协议与设备驱动通信的通用接口,最下面是设备驱动程序。

3)系统调用接口:为应用程序提供访问内核网络子系统的方法:Socket系统调用。
4)协议无关接口:实现一组通用函数来访问各种不同的协议:通过socket实现。Linux 中的socket 使用
struct sock来描述,这个结构包含了特定socket 所需要的所有状态信息,还包括
socket 所使用的特定协议和在socket 上可以执行的一些操作

5)网络协议层用于实现各种具体的网络协议,如:TCP、UDP 等
6)设备无关接口:设备无关接口将协议与各种网络设备驱动连接在一起。
这一层提供一组通用函数供底层网络设备驱动程序使用,让它们可以对高层协议栈进行操作。首先,设备驱
动程序可能会通过调用register_netdevice 或unregister_netdevice 在内核中进行注册或注销。调
用者首先填写net_device 结构,然后传递这个结构进行注册。内核调用它的init 函数(如果定义了这种函
数),然后执行一组健全性检查,并将新设备添加到设备列表中(内核中的活动设备链表)
要从协议层向设备发送数据,需要使用dev_queue_xmit函数,这个函数对数据进行排
队,并交由底层设备驱动程序进行最终传输报文的接收通常是使用netif_rx执行的。当底层设备驱动
程序接收到一个报文(包含在所分配的sk_buff 中)时,就会通过调用netif_rx 将数据上传至设备
无关层,然后,这个函数通过netif_rx_schedule 将sk_buff 在上层协议队列中进行排队,供以后进行处理。

7)驱动程序:网络体系结构的最底部是负责管理物理网络设备的设备驱动程序层

 

****************************************************************************************************************************************
 

二、网络驱动程序设计:
每个网络接口都由一个net_device结构来描述,该结构可使用如下内核函数动态分配:
1、struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *))
   sizeof_priv 私有数据区大小;mask:设备名;setup 初始化函数
  
2、struct net_device *alloc_etherdev(int sizeof_priv)

  struct net_device
  {
   char name[IFNAMSIZ] ;//   设备名,如:eth%d  //%d表示由内核自动获取。
   vunsigned long state ;//   设备状态
   vunsigned long base_addr ;//   I/O 基地址
   vunsigned int irq ;//   中断号
      ...
  }
 
3、net_device初始化:int (*init)(struct net_device *dev)
   初始化函数。该函数在register_netdev时被调用来完成对net_device 结构的初始化
  
   net_device和字符驱动一样, 网络设备也要声明能操作它的函数。有些操作可以保留为NULL, 有的可以通过ether_setup 来使用默认设置。网络
接口的设备方法可分为两组:基本的和可选的,基本方法包括那些使用接口所必需的;可选的方法实现更多高级的功能。

4、基本方法:
   int (*open)(struct net_device *dev) //打开接口。ifconfig 激活时,接口将被打开。
   int (*stop)(struct net_device *dev)  //停止接口。该什么时候调用呢?
   int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev) //数据发送函数。
  
5、可选操作:
   int (*do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd) //处理特定于接口的ioctl 命令
   int (*set_mac_address)(struct net_device *dev, void *addr) //改变Mac地址的函数,需要硬件支持该功能
  
6、设备注册:
   网络接口驱动的注册方式与字符驱动不同之处在于它没有主次设备号,并使用如下函数注册。
   int register_netdev(struct net_device *dev)  
  
7、sk_buff 存放网络包:
    Linux内核中的每个网络数据包都由一个套接字缓冲区结构struct sk_buff 描述,即一个
    sk_buff结构就是一个包,指向sk_buff的指针通常被称做skb。
    struct sk_buff
    {
    struct device *dev;  //处理该包的设备
    __u32 saddr; //IP源地址
    __u32 daddr; //IP目的地址
    __u32 raddr; //IP路由器地址     
    
    unsigned char *head;    //分配空间的开始
    unsigned char *data;     //有效数据的开始
    unsigned char *tail;       //有效数据的结束
    unsigned char *end;     //分配空间的结束
    unsigned long len; //有效数据的长度
    
    };
   
8、skb操作函数:
   操作sk_buff的内核函数如下: struct sk_buff *alloc_skb(unsigned int len, int priority)
   分配一个sk_buff 结构,供协议栈代码使用 struct sk_buff *dev_alloc_skb(unsigned int len)分配一个sk_buff 结构,供驱动代码使用
  
   unsigned char *skb_push(struct sk_buff *skb, int len) //向后移动skb的tail指针,并返回tail移动之前的值。  这样才能再填入后面的值
   unsigned char *skb_put(struct sk_buff *skb, int len) //向前移动skb的head指针,并返回head移动之后的值     这样才不会覆盖后面的值
   kfree_skb(struct sk_buff *skb)  //释放一个sk_buff 结构,供协议栈代码使用
   dev_kfree_skb(struct sk_buff *skb) //释放一个sk_buff 结构,供驱动代码使用
  
9、设备打开:
    Open 请求任何它需要的系统资源并且启动
    接口:
    注册中断,DMA等
    设置寄存器,启动设备
    启动发送队列
   
    例如:
    int net_open(struct net_device *dev)
  {
    /*申请中断*/
    request_irq(dev->irq, &net_interrupt, SA_SHIRQ,
    “dm9000”, dev);
    /* 设置寄存器,启动设备*/
    ...... ...... ...... ......
    /*启动发送队列*/
    netif_start_queue(dev);
  }
   
10、数据发送:
    当核心需要发送一个数据包时,它调用hard_start_transmit函数,该函数将最终调用到net_device结构中的hard_start_xmit函数指针。
11、数据接收
    网络接口驱动可以实现两种方式的报文接收: 中断和查询,Linux中驱动多采用中断方式   
   
    接收流程:
    1、分配Skb: 
       skb = dev_alloc_skb(pkt->datalen + 2)
  2、从硬件中读取数据到Skb
  3、调用netif_rx将数据交给协议栈
     netif_rx(skb)
  
12、中断处理:
  网络接口通常支持3种类型的中断: 新报文到达中断、报文发送完成中断和出错中断。中
  断处理程序可通过查看网卡中的中断状态寄存器,来分辨出中断类型。  
  

 

 

转载于:https://www.cnblogs.com/pangblog/p/3317975.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360419.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android 自定义弹窗diss,Android中自定义PopupWindow,动态弹窗。

我的第一篇博客,咱们直奔主题。先上个效果图在android中自定义PopupWindow:1、首先定义好你想要显示的窗口的布局文件,再实例化一个View对象:窗口布局可灵活变化,dialog_layout.xml代码如下:android:id&quo…

拼图项目的动机和目标

几周前,我写了一篇关于Jigsaw项目如何破坏现有代码的文章 。 那么,我们能得到什么回报呢? 让我们看一下项目解决的痛点及其在Java 9中解决问题的目标。 系列 这篇文章是正在进行的有关拼图项目系列的一部分。 按照推荐的顺序(不同…

android中按一个按钮弹出字,允许用户在Android中长按一次即可编辑按钮文字

我想允许App用户在Android中更改Button文本。 当用户单击按钮时,它应该执行某些操作,但是当他/她长按按钮时,将弹出一个编辑文本,并且无论用户键入什么内容都应另存为按钮文本。到目前为止,我已经完成了以下操作。btn1…

关于单元测试脚手架的几点思考

莱昂:Luc Besson的专业人士 当我开始通过创建相同的对象并准备数据来运行测试来重复使用单元测试方法时,我对设计感到失望。 带有大量代码重复的长时间测试方法看起来并不正确。 为了简化和缩短它们,基本上有两个选项,至少在Java…

android 使用c 代码实现,JNI开发实现helloworld,调用自己的C代码实现(1)

JNI开发,实现自己的C代码,helloworld在这里实现一个简单的demo,完成加载自己的C代码使用Android studio,一步一步教你实现在屏幕上显示出helloworld如下图显示,配置号NDK的路径,没有路径的需要自己下载,在A…

使用WSO2 ESB进行邮件内容过滤

每个集成架构师或开发人员都应该熟悉Gregor Hohpe和Bobby Woolf所描述的企业集成模式(EIP) 。 模式之一是“内容消息过滤器” (不要与消息过滤器模式混淆)。 使用不同的Mediator在WSO2中有多种方法可以实现此目的。 一种方法是使…

android壁纸应用,HPSTR - 可能是你见过最会玩的壁纸应用 - Android 应用 - 【最美应用】...

今天这款 HPSTR 壁纸应用也不例外,HPSTR 主要的壁纸素材源来自 Unsplash(ios/android)、500px(android)、Reddit(android)这些素材源的图片都很优秀,特别是 Unsplash 它是著名的无版权图片网站。它家主要以风景为主,数量也足够多,…

android sqlite批量操作,Android: SQLite批量插入数据的最佳实践

大家都知道,Android里数据库用的是SQLite。在实际开发过程中,我们有时候会遇到批量插入数据的场景。这篇文章给大家分享一个小技巧,让批量插入数据达到最快的目的。首先,我先创建一个Table,里面只有一个字段&#xff1…

c语言实现linux下的top命令来获取cpu利用率_有用的一篇笔记,linux 调优各项监控指标...

自开始负责生产环境部署,中间遇到了若干线上环境内存以及CPU的问题。由于微服务以及容器的流行,现在已经可以很方便的使用 K8s prometheus grafana alert 的方式进行监控,这足以覆盖大部分场景。最重要的事情已经交由最适合的组件去做&…

rip协议中周期性广播路由信息的报文_技术实操||距离矢量路由协议-RIP

距离矢量路由协议—RIP01距离矢量路由协议概述路由信息协议RIP(RoutingInformation Protocol)的简称,它是一种基于距离矢量(Distance-Vector)算法的协议,使用跳数作为度量来衡量到达目的网络的距离。RIP主要应用于规模较小的网络中。RIP是一种比较简单的…

使用tinylog 1.0简化您的日志记录

tinylog的大小仅为75 KB,是广泛使用的经典日志记录框架Log4j和Logback的轻型替代方案。 经过三年的开发,最终版本1.0刚刚于 3月底发布 。 在几个设计问题中,tinylog采取了与Java中经典日志记录框架完全不同的方法。 本文将介绍与Log4j和Logba…

华谊兄弟出现什么问题_什么是语言训练?这就要从语言问题的出现说起了

开口、发音是每一个孩子在语言发展过程中所不可少的经历,他们从周围环境中获取到的各种信息转化为想要表达的内容。虽然一开始孩子的语言并没有成年人那么流畅和准确,但随着时间的推移,他们的说话发音愈发成熟。只是,并不是所有孩…

【算法提升—力扣每日一刷】五日总结【12/18--12/22】

文章目录 2023/12/18LeetCode每日一刷:[20. 有效的括号](https://leetcode.cn/problems/valid-parentheses/) 2023/12/19LeetCode每日一刷:[150. 逆波兰表达式求值(后缀表达式运算)](https://leetcode.cn/problems/evaluate-rever…

CompletableFuture不能被打断

我已经写了很多有关InterruptedException和中断线程的文章 。 简而言之,如果您没有Future.cancel()调用Future.cancel()那么Future将终止待处理的get() ,但还将尝试中断基础线程。 这是一个非常重要的功能,可以更好地利用线程池。 我还写信总…

crio电压采集 labview_NI cDAQ917采集温度方法

NI cDAQ-9171是一款由总线供电的单槽NI CompactDAQ USB机箱,适合较小的便携式传感器测量系统。cDAQ-9171可与50多款专用测量模块配合使用,用于构建模拟输出、数字I/O或计数器/定时器测量系统。这些模块适用于各种传感器测量,包括热电偶、RTD、…

android finish 区别,Android Activity类finish、onDestory和System.exit介绍

image.pngfinish函数Activity.finish()Call this when your activity is done and should be closed.在你的activity动作完成的时候,或者Activity需要关闭的时候,调用此方法。当调用此方法的时候,系统只是将最上面的Activity移出了栈&#xf…

在JVM中记录世界停顿

不同的事件可能导致JVM暂停所有应用程序线程。 这种暂停称为世界停止(STW)暂停。 触发STW暂停的最常见原因是垃圾回收( 例如github中的示例 ),但是不同的JIT操作( 示例 ),偏向锁吊销…

jOOQ与Hibernate:何时选择哪个

Hibernate已成为Java生态系统中的事实上的标准,事实上, 如果标准对您很重要 ,并且如果您将JCP与ISO,ANSI,IEEE等置于同一级别,那么Hibernate也是实际的JavaEE标准实现。 本文的目的不是讨论标准&#xff0…

linux怎么才能算telnet成功_怎么表白才算成功呢

要怎样表白才算成功呢?其实如果对方也有点喜欢你的,对你有点感觉的,不管怎样表白,你都会成功的,相反,如果对方本身就对你没感觉的,不管你要怎么轰轰烈烈的表白,你都不会成功。下面&a…

我们真的仍然需要32位JVM吗?

即使到了今天(2015年),我们仍然有两个版本或Oracle HotSpot JDK –已调整为32或64位体系结构。 问题是我们是否真的想在服务器甚至笔记本电脑上使用32位JVM? 我们应该有很受欢迎的意见! 如果只需要较小的堆&#xff0c…