深入理解 Neutron -- OpenStack 网络实现:VXLAN 模式_br_int-程序员宅基地

技术标签: vxlan  网络  虚拟化  openstack  云计算虚拟化  ovs  

VXLAN 模式下,网络的架构跟 GRE 模式类似,所不同的是,不同节点之间通过 VXLAN 隧道互通,即虚拟化层是采用的 VXLAN 协议。基本结构如下图所示:

这里写图片描述

从这张架构图中,我们可以明显的看到有两个物理主机:计算节点和网络节点,这是因为采用了网络节点集中式的部署方式。

1) 在计算节点上创建虚拟机之后,虚拟机虚拟网卡通过linux bridge(这里的qbr)与br-int连起来。这里的A就是虚拟机的虚拟网卡,B是一个tap设备。C与D是连接linux bridge与br-int的一对tap设备,一般C叫qvb,D叫qvo。br-int是ovs虚拟化出来的网桥,作为虚拟机交换机的功能。br-int通过patch-tun连接到ovs虚拟化出来的网桥br-tun上,br-tun作为通信层,通过tunnel与其他计算节点和网络节点通信。

我们在这个架构中,使用的OpenvSwitch实现虚拟交换设备的,为什么会出现Linux Bridge呢?OpenStack Networking Administration Guide给出了这样的解释:

“Ideally, the TAP device vnet0 would be connected directly to the integration bridge, br-int. Unfortunately, this isn’t possible because of how OpenStack security groups are currently implemented. OpenStack uses iptables rules on the TAP devices such as vnet0 to implement security groups, and Open vSwitch is not compatible with iptables rules that are applied directly on TAP devices that are connected to an Open vSwitch port.”

其实就是说,OpenvSwitch不支持现在的OpenStack的实现方式,因为OpenStack是把iptables规则丢在TAP设备中,以此实现了安全组功能。没办法,所以用了一个折衷的方式,在中间加一层,用Linux Bridge来实现,这样,就多了一个qbr网桥。

2)在网络节点这边与计算节点类似,也有两个ovs的网桥br-tun与br-int。如果有多个虚拟机路由会通过tap设备连接到br-int。br-ex桥的一个接口挂载的物理接口 eth0上,网包将从这个接口发送到外部网络上。另外一个是 qg-xxx 这样的接口,是连接到 router 服务的网络名字空间中,里面绑定一个路由器的外部 IP,作为 NAT 时候的地址。

其中,节点网络配置如下所示,注意数据网络接口需要 IP 地址,因为是隧道协议需要底下的三层转发支持。

网络节点

  • eth0: 9.186.100.77/24 作为管理网络(同时也是公共网络)。
  • eth1: 10.0.100.77/24 作为数据网络接口。

计算节点

  • eth0: 9.186.100.88/24 作为管理网络(同时也是公共网络)。
  • eth1: 10.0.100.88/24 作为数据网络接口。

计算节点

计算节点上运行着虚拟机。如果不启用 DVR 特性,则所有的网络相关的服务,都在网络节点上进行。即计算节点上的网络只需要实现二层转发即可。

br-int

集成网桥 br-int 规则比较简单,作为一个正常的二层交换机使用。无论下面虚拟化层是哪种技术实现,集成网桥是看不到的,只知道根据 vlan 和 mac 进行转发。

Bridge br-int
       fail_mode: secure
       Port br-int
           Interface br-int
               type: internal
       Port "qvoc4493802-43"
           tag: 1
           Interface "qvoc4493802-43"
       Port patch-tun
           Interface patch-tun
               type: patch
               options: {peer=patch-int}
       Port "qvof47c62b0-db"
           tag: 1
           Interface "qvof47c62b0-db"

所连接接口除了从安全网桥过来的 qvo-xxx(每个虚拟机会有一个),就是一个往外的 patch-tun 接口,连接到 br-tun 网桥。

其中,qvo-xxx 接口上会为每个网络分配一个内部 vlan 号,比如这里是同一个网络启动了两台虚机,所以 tag 都为 1。

$ sudo ovs-ofctl dump-flows br-int
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=52889.682s, table=0, n_packets=161, n_bytes=39290, idle_age=13, priority=1 actions=NORMAL
 cookie=0x0, duration=52889.451s, table=23, n_packets=0, n_bytes=0, idle_age=52889, priority=0 actions=drop

转发规则表 0 中是对所有包进行 NORMAL,表 23 中是所有包直接丢弃、其实逻辑很简单,br-int 被当作一个二层交换机,根据 vlan 和 mac 进行转发。

br-tun

br-tun 作为虚拟化层网桥,规则就要复杂一些。 要将内部过来的网包进行合理甄别,内部带着正确 vlan tag 过来的,从正确的 tunnel 扔出去;外面带着正确 tunnel 号过来的,要改到对应的内部 vlan tag 扔到里面。

Bridge br-tun
        fail_mode: secure
        Port "vxlan-0a00644d"
            Interface "vxlan-0a00644d"
                type: vxlan
                options: {df_default="true", in_key=flow, local_ip="10.0.100.88", out_key=flow, remote_ip="10.0.100.77"}
        Port patch-int
            Interface patch-int
                type: patch
                options: {peer=patch-tun}
        Port br-tun
            Interface br-tun
                type: internal

其中,端口 br-tun 是内部端口,vxlan-0a00644d 这样的端口是向其它节点发包时候的 VXLAN 隧道端点,patch-int 端口通过一条管道连接到 br-int 上的 patch-tun 端口。

正常情况下,虚拟机的流量经过 br-int 转发,经过 patch-tun 端口,抵达 patch-int 端口,从而到达 br-tun 网桥,该网桥根据自身规则将合适的网包经过 VXLAN 隧道送出去。

$ sudo ovs-ofctl dump-flows br-tun
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=329.194s, table=0, n_packets=31, n_bytes=2906, idle_age=29, priority=1,in_port=1 actions=resubmit(,2)
 cookie=0x0, duration=325.847s, table=0, n_packets=14, n_bytes=1591, idle_age=33, priority=1,in_port=2 actions=resubmit(,4)
 cookie=0x0, duration=328.954s, table=0, n_packets=6, n_bytes=480, idle_age=321, priority=0 actions=drop
 cookie=0x0, duration=328.712s, table=2, n_packets=9, n_bytes=694, idle_age=33, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
 cookie=0x0, duration=328.465s, table=2, n_packets=22, n_bytes=2212, idle_age=29, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22)
 cookie=0x0, duration=328.223s, table=3, n_packets=0, n_bytes=0, idle_age=328, priority=0 actions=drop
 cookie=0x0, duration=50.703s, table=4, n_packets=12, n_bytes=1451, idle_age=33, priority=1,tun_id=0x3e9 actions=mod_vlan_vid:1,resubmit(,10)
 cookie=0x0, duration=327.979s, table=4, n_packets=2, n_bytes=140, idle_age=94, priority=0 actions=drop
 cookie=0x0, duration=327.742s, table=10, n_packets=12, n_bytes=1451, idle_age=33, priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1
 cookie=0x0, duration=38.551s, table=20, n_packets=9, n_bytes=694, hard_timeout=300, idle_age=33, hard_age=33, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:83:95:fa actions=load:0->NXM_OF_VLAN_TCI[],load:0x3e9->NXM_NX_TUN_ID[],output:2
 cookie=0x0, duration=327.504s, table=20, n_packets=0, n_bytes=0, idle_age=327, priority=0 actions=resubmit(,22)
 cookie=0x0, duration=50.94s, table=22, n_packets=11, n_bytes=1334, idle_age=29, dl_vlan=1 actions=strip_vlan,set_tunnel:0x3e9,output:2
 cookie=0x0, duration=327.261s, table=22, n_packets=10, n_bytes=808, idle_age=51, priority=0 actions=drop

这些才是真正处理 VXLAN 数据包的 rule,流程如下:

这里写图片描述

table0 中的规则

cookie=0x0, duration=329.194s, table=0, n_packets=31, n_bytes=2906, idle_age=29, priority=1,in_port=1 actions=resubmit(,2)
 cookie=0x0, duration=325.847s, table=0, n_packets=14, n_bytes=1591, idle_age=33, priority=1,in_port=2 actions=resubmit(,4)
 cookie=0x0, duration=328.954s, table=0, n_packets=6, n_bytes=480, idle_age=321, priority=0 actions=drop

从 1 端口(patch-int)过来的网包,扔给表 2 处理,从 2 端口(vxlan-0a00644d)进来的网包,扔给表 4 处理。即一个处理来自内部 vm 的,一个处理来自外面的 vxlan 隧道的

table2 中的规则

cookie=0x0, duration=53316.397s, table=2, n_packets=0, n_bytes=0, idle_age=53316, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
cookie=0x0, duration=53316.162s, table=2, n_packets=161, n_bytes=39562, idle_age=422, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22)

即里面过来的单播包,扔给表 20 处理;多播和广播包,扔给表 22 处理。

table3 中的规则

cookie=0x0, duration=328.223s, table=3, n_packets=0, n_bytes=

丢弃所有包。

table4 中的规则

cookie=0x0, duration=50.703s, table=4, n_packets=12, n_bytes=1451, idle_age=33, priority=1,tun_id=0x3e9 actions=mod_vlan_vid:1,resubmit(,10)
 cookie=0x0, duration=327.979s, table=4, n_packets=2, n_bytes=140, idle_age=94, priority=0 actions=drop

对于外部来的数据,匹配给定的 tunnel 号,添加对应的 vlan 号,扔给表 10 去学习一下后扔到 br-int 网桥。

table10 中的规则

cookie=0x0, duration=327.742s, table=10, n_packets=12, n_bytes=1451, idle_age=33, priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1

主要作用是学习外部(从 tunnel)进来的包,往表 20 中添加对返程包的正常转发规则,并且从 patch-int 扔给 br-int。
使用了 openvswitch 的 learn 动作。该动作能根据处理的流来动态修改其它表中的规则。
具体来看 learn 规则:

  • table=20 说明是修改表 20 中的规则,后面是添加的规则内容;
  • NXM_OF_VLAN_TCI[0..11],匹配跟当前流同样的 VLAN 头,其中 NXM 是 Nicira Extensible Match 的缩写;
  • NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],包的目的 mac 跟当前流的源 mac 匹配;
  • load:0->NXM_OF_VLAN_TCI[],将 vlan 号改为 0;
  • load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],将 tunnel 号修改为当前的 tunnel 号;
  • output:NXM_OF_IN_PORT[],从当前入口发出。

table20 中的规则

cookie=0x0, duration=38.551s, table=20, n_packets=9, n_bytes=694, hard_timeout=300, idle_age=33, hard_age=33, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:83:95:fa actions=load:0->NXM_OF_VLAN_TCI[],load:0x3e9->NXM_NX_TUN_ID[],output:2
cookie=0x0, duration=327.504s, table=20, n_packets=0, n_bytes=0, idle_age=327, priority=0 actions=resubmit(,22)

其中,第一条规则就是表 10 学习来的结果。对于 vlan 号为 1,目标 mac 是 fa:16:3e:83:95:fa(之前,我们从虚拟机内 ping 10.0.0.1,这个 mac 作为源 mac 从 tunnel 来过)的网包,去掉 vlan 号,添加当时的 vxlan 号,并从 tunnel 发出。
对于没学习到规则的网包,则扔给表 22 处理

table22 中的规则

cookie=0x0, duration=50.94s, table=22, n_packets=11, n_bytes=1334, idle_age=29, dl_vlan=1 actions=strip_vlan,set_tunnel:0x3e9,output:2
cookie=0x0, duration=327.261s, table=22, n_packets=10, n_bytes=808, idle_age=51, priority=0 actions=drop

检查如果 vlan 号正确,则去掉 vlan 头后从 tunnel 扔出去。

网络节点

网络节点担负着进行网络服务的任务,包括DHCP、路由和高级网络服务等。一般包括三个网桥:br-tun、br-int 和 br-ex。

br-tun

跟计算节点类似,br-tun 作为虚拟化层网桥。 要将内部过来的网包进行合理甄别,内部带着正确 vlan tag 过来的,从正确的 tunnel 扔出去;外面带着正确 tunnel 号过来的,要改到对应的内部 vlan tag 扔到里面。

包括两个接口,跟其它接点形成 tunnel 的 vxlan-xxx 端口,以及跟 br-int 互连的 patch-int 端口。

Bridge br-tun
        fail_mode: secure
        Port br-tun
            Interface br-tun
                type: internal
        Port "vxlan-0a006458"
            Interface "vxlan-0a006458"
                type: vxlan
                options: {df_default="true", in_key=flow, local_ip="10.0.100.77", out_key=flow, remote_ip="10.0.100.88"}
        Port patch-int
            Interface patch-int
                type: patch
                options: {peer=patch-tun}

其中,端口 br-tun 是内部端口,vxlan-0a00644d 这样的端口是向其它节点发包时候的 VXLAN 隧道端点,patch-int 端口通过一条管道连接到 br-int 上的 patch-tun 端口。

查看 br-tun 上的转发规则:

$ sudo ovs-ofctl dump-flows br-tun
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=422.153s, table=0, n_packets=1073, n_bytes=107845, idle_age=96, priority=1,in_port=1 actions=resubmit(,2)
 cookie=0x0, duration=185.009s, table=0, n_packets=1076, n_bytes=102922, idle_age=96, priority=1,in_port=2 actions=resubmit(,4)
 cookie=0x0, duration=421.853s, table=0, n_packets=6, n_bytes=480, idle_age=62414, priority=0 actions=drop
 cookie=0x0, duration=421.552s, table=2, n_packets=1047, n_bytes=105725, idle_age=96, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
 cookie=0x0, duration=421.252s, table=2, n_packets=26, n_bytes=2120, idle_age=61953, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22)
 cookie=0x0, duration=420.939s, table=3, n_packets=0, n_bytes=0, idle_age=62420, priority=0 actions=drop
 cookie=0x0, duration=394.249s, table=4, n_packets=1076, n_bytes=102922, idle_age=96, priority=1,tun_id=0x3e9 actions=mod_vlan_vid:1,resubmit(,10)
 cookie=0x0, duration=420.628s, table=4, n_packets=0, n_bytes=0, idle_age=62420, priority=0 actions=drop
 cookie=0x0, duration=420.304s, table=10, n_packets=1076, n_bytes=102922, idle_age=96, priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1
 cookie=0x0, duration=1314.149s, table=20, n_packets=1006, n_bytes=101338, hard_timeout=300, idle_age=96, hard_age=95, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:52:7a:f2 actions=load:0->NXM_OF_VLAN_TCI[],load:0x3e9->NXM_NX_TUN_ID[],output:2
 cookie=0x0, duration=419.977s, table=20, n_packets=0, n_bytes=0, idle_age=62419, priority=0 actions=resubmit(,22)
 cookie=0x0, duration=184.683s, table=22, n_packets=3, n_bytes=230, idle_age=61953, dl_vlan=1 actions=strip_vlan,set_tunnel:0x3e9,output:2
 cookie=0x0, duration=419.668s, table=22, n_packets=23, n_bytes=1890, idle_age=61961, priority=0 actions=drop

这些规则跟计算节点上的 br-tun 网桥规则类似,组成如下图所示的转发逻辑。

这里写图片描述

table0中的规则:

从 1 端口(patch-int)进来的网包,扔给表 2 处理,从 2 端口(vxlan-0a00644d)进来的网包,扔给表 4 处理。即一个处理来自内部 br-int 的(这上面挂载着所有的网络服务,包括路由、DHCP 等),一个处理来自外面的 VXLAN 隧道的。

br-int

集成网桥 br-int 规则比较简单,作为一个正常的二层交换机使用。无论下面虚拟化层是哪种技术实现,集成网桥是看不到的,只知道根据 vlan 和 mac 进行转发。

Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal
        Port "qr-694450d6-f6"
            tag: 1
            Interface "qr-694450d6-f6"
                type: internal
        Port "tap13685e28-b0"
            tag: 1
            Interface "tap13685e28-b0"
                type: internal
        Port patch-tun
            Interface patch-tun
                type: patch
                options: {peer=patch-int}

所连接接口包括:

  • tap-xxx,连接到网络 DHCP 服务的命名空间;
  • qr-xxx,连接到路由服务的命名空间;
  • 往外的 patch-tun 接口,连接到 br-tun 网桥。
    其中网络服务接口上会绑定内部 vlan 号,每个号对应一个网络。

br-ex

当数据从router中路由出来后,就会通过K、L传送到br-ex这个虚拟网桥上,而br-ex实际上是混杂模式加载在物理网卡上,实时接收着网络上的数据包。至此,我们的计算节点上的VM就可以与外部的网络进行自由的通信了。当然,前提是我们要给这个VM已经分配了float-ip。

核心接口有两个:一个是挂载的物理接口上,如 eth0,网包将从这个接口发送到外部网络上。
另外一个是 qg-xxx 这样的接口,是连接到 router 服务的网络名字空间中,里面绑定一个路由器的外部 IP,作为 NAT 时候的地址,另外,网络中的 floating IP 也放在这个网络名字空间中。

Bridge br-ex
        Port "eth0"
            Interface "eth0"
        Port br-ex
            Interface br-ex
                type: internal
        Port "qg-e76de35e-90"
            Interface "qg-e76de35e-90"
                type: internal

网桥的规则也很简单,作为一个正常的二层转发设备即可。

$ sudo ovs-ofctl dump-flows br-ex
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=75072.257s, table=0, n_packets=352212, n_bytes=85641148, idle_age=0, hard_age=65534, priority=0 actions=NORMAL
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_15437629/article/details/78702829

智能推荐

HTML+CSS常用代码_<dl><dt></dt></dl>图文混排-程序员宅基地

文章浏览阅读1.5k次,点赞12次,收藏94次。HTML+CSS常用代码(笔记)注释标签:对代码进行说明<!-- 单行注释,也可以对多行文字进行注释 -->常用格式标签<b>加粗</b> <i>斜体</i> <strong>(粗字体)强调文本</strong><sup>上标</sup> <sub>下标</s..._图文混排

java刷算法题总结_java刷算法题常用的函数及技巧-程序员宅基地

文章浏览阅读1.1k次,点赞3次,收藏13次。算法之路,任重道远。作为一枚刷了一学期算法的大二生,寒假总结一下用Java刷题的技巧????1️⃣输入一、读取输入并赋值1.顺序访问,且只使用一次数字巧用for循环,直接比,注意第一组数据处理strnextInt()只读取了数字n却没有读取换行符,下一个nextLine()会读取换行符并解析为空串nextLine 一行 & next只读字str转intString 字符串转整型 int 有以下两种方式:Integer.parseInt(str)Integer._java刷算法题常用的函数及技巧

WeChat_微信小程序跳一跳辅助_微信小程序跳一跳外挂-程序员宅基地

文章浏览阅读4k次,点赞2次,收藏3次。上次在GitHub上explore里榜首发现一个有趣的项目,对于这个我的评价是:“技术活儿,可没法儿赏啊!”教你如何用python来玩微信跳一跳!这是其原理,并不复杂,通俗易懂!原理说明将手机点击到《跳一跳》小程序界面用 ADB 工具获取当前手机截图,并用 ADB 将截图 pull 上来adb shell screencap -p /sdca_微信小程序跳一跳外挂

STM32开发——定时器led、PWM呼吸灯_led点亮时间利用定时器实现时间的控制 stm32-程序员宅基地

文章浏览阅读1.4k次。定时器分类:基本定时器(TIM6~TIM7)通用定时器(TIM2~TIM5)高级定时器(TIM1和TIM8)A.输入捕获B.输出比较C.PWM 生成(边缘或中间对齐模式)D.单脉冲模式输出A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)C.输入捕获D.输出比较E.支持针对定位的增量(正交)编码器和霍尔传感器电路F.触发输入作为外部时钟或者按周期的电流管理。_led点亮时间利用定时器实现时间的控制 stm32

IOS学习—强引用(__strong)和 弱引用(__weak)_ios __strong-程序员宅基地

文章浏览阅读2.6k次。转载于开源中国在Objective-C的ARC模式中,id obj1 = [[NSObject alloc] init]; 这里虽然没有显示的声明为__strong,但是Objective-C默认声明的一个对象就为__strong,即: id obj1 = [[NSObject alloc] init]; 和 id __strong obj1 = [[NSObject alloc] init_ios __strong

ubuntu18.04下qt5.9编译错误: -1: error: cannot find -lGL_:-1: error: /usr/local/qt-5.9/lib/libqt5core.so: u-程序员宅基地

文章浏览阅读2.1k次。只要安装libGL即可:sudo apt-get install libqt4-devsudo apt update再重新编译就ok啦 _:-1: error: /usr/local/qt-5.9/lib/libqt5core.so: undefined reference to `uca

随便推点

什么时候用List、Set或Map(Java中的集合框架体系)_业务开发什么时候使用list-程序员宅基地

文章浏览阅读2.2k次,点赞15次,收藏42次。集合框架体系集合是Java中提供的一种容器,可以用来存储多个数据;而由于存储的方式不同,就形成了很多不同的体系结构,统称为集合框架体系。归为两大类 : Conllection 和 Map Collection List ArrayList 1、排序有序,可重复 2、底层使用数组 3、查询快......_业务开发什么时候使用list

SQL中IF ELSE及MySQL伪列rownum的使用_mysql 如何使用if else 生成伪列-程序员宅基地

文章浏览阅读290次。编写SQL语句时难免会遇到各种条件判断,例如统计:count(case when then end)今天,我们要说的是if判断,eg:SELECT IF(c19='1','已评价','未评价')c19 FROM A05;关于伪列,广为人知的是oracle有伪列rownum,因为一些需求需要用mysql实现类似Oracle的伪列,方法方式如下:SELECT rowid, i01..._mysql 如何使用if else 生成伪列

【C++】虚函数及其内存布局_c++虚函数内存分布-程序员宅基地

文章浏览阅读1.7k次,点赞5次,收藏20次。一、函数调用捆绑把函数体与函数调用相联系称为捆绑。当捆绑在程序运行之前(由编译器和连接器)完成时,称为早捆绑。C编译只有一种函数调用方式,就是早捆绑。早捆绑引起的问题:因为编译器在只有对象的地址时它并不知道要调用的正确函数。根据对象的类型,捆绑发生在运行时,这种捆绑方式称为晚捆绑,又称动态捆绑。二、虚函数对于特定的函数,为了引起晚捆绑,C++要求在基类中声明这个函数时使用virtual关键字,这样的函数称为虚函数。晚捆绑只对virtual函数起作用,而且只在使用含有virtual函._c++虚函数内存分布

matlab 相位校正,科学网—全相位比值校正法 - 王兆华的博文-程序员宅基地

文章浏览阅读709次。加hann窗全相位比值校正法和加hann窗fft比值校正法校正方法类同,只须将二个振幅比改为振幅开方比即可。这里加hann窗是关键,过去测试时,直接调用Matlab中的hann(N)窗,频率和振幅校正效果差,见表5加hann窗全相位比值校正法测试结果。表4为加n-hann窗全相位比值校正法,其频率校正精度,相位校正精度和振幅校正精度都很高,甚至可以和表1加n-hann卷积窗apfft/apfft校..._比值校正法频谱校正matlab

创建登录界面_建网站登录页面-程序员宅基地

文章浏览阅读334次。package zhoushi;import javax.swing.*;//调用库import java.awt.*;import java.awt.event.*;public class jh extends JFrame implements ActionListener{//创建类jh继承JFrame,实现接口ActionListener JPanel log;//定义变量_建网站登录页面

win10安装linux虚拟机并配置shell工具连接_shell确认虚拟机光盘连接-程序员宅基地

文章浏览阅读1k次。1:虚拟机安装先看怎么用VMware安装一个虚拟机,全部放图,一步步来。主要还是以防以后我自己忘记怎么搞了,老了,记性不好了。VMware就在网上随便下载一个了,镜像我会在下面放上我的或者大家也可以自己去网上下一个。第一步:新建虚拟机第二步:选择类型第三步:选择映像文件,一般都会检测到,检测不到就只能自己打开浏览去找吧!第四步:给虚拟机命名,可以更改虚拟机安装位置。反正我是不会装在系统盘的,这辈子都不会的o(´^`)o第五步:默认选择是虚拟磁盘拆分成多个文件,但._shell确认虚拟机光盘连接

推荐文章

热门文章

相关标签