一、iperf3工作原理

iperf3主要的功能是测试基于特定路径的带宽,在客户端和服务器端建立连接(三次握手)后,客户端发送一定大小的数据报并记下发送的时间,或者客户端在一定的时间内发送数据并记下发送的总数据。带宽的大小等于发送的总数据除以发送的总时间。对服务器端来说,在连接建立时间内,接收的总数据除以所花时间即为服务器端所测得的带宽。

iperf3测试UDP的性能时,客户端可以指定UDP数据流的速率。客户端发送数据时,将根据客户提供的速率计算数据报发送之间的时延,客户还可以指定发送数据报的大小。每个发送的数据报包含一个ID号,用来唯一地标识该报文。服务器端则根据该ID号来确定数据报丢失和乱序。当把UDP报文大小设置可以将整个报文放入IP层的包(packet)内时,那么UDP所测得的报文丢失数据即为IP层包的丢失数据。这提供了一个有效的测试包丢失情况的方法。数据报传输延迟抖动(Jitter)的测试由服务器端完成,客户发送的报文数据包含有发送时间戳,服务器端根据该时间信息和接收到报文的时间戳来计算传输延迟抖动。传输延迟抖动反映传输过程中是否平滑。由于它是一个相对值,所以并不需要客户端和服务器端时间同步。

由上介绍我们可以知道iperf3的功能增加了操作系统网络度量的能力,而携带Liteos_A内核的OpenAtom OpenHarmony(以下简称“OpenHarmony”)操作系统目前还不支持这个功能,特此尝试把iperf3移植到支持Liteos_A内核的OpenHarmony操作系统中,并作此文分享一些心得。

二、iperf3移植过程

iperf3可以运行在Linux和Windows平台下,其使用了标准的POSIX接口,因此将iperf3移植到Liteos_A上,目前Liteos_A支持用户态和内核态的命令,这个也造成了移植的很大困难,所以以下将2种添加命令的方式都记录下,供读者参考。

1. 确定库的类型

OpenHarmony有如下几种目标类型:

executable: 生成可执行文件,对于Liteos_A,在目录/bin下可以找到可执行文件

shared_library: 生成.dll或.so动态链接库、对于Liteos_A,在目录/lib或者  /usr/lib下可以找到动态库

static_library: 生成.lib或.a静态链接库

group: 生成依赖关系组

action: 运行脚本以生成文件

根据以上几种类型的描述可知,将iperf3移植成executable类型的组件最为合适。

2. 添加库到工程中

将源码下载到Linux下并解压,执行./configure,生成iperf_config.h,将iperf3的源码拷贝到OpenHarmony代码库中合适的位置,如下将iperf3添加到/third_party目录下。

需要注意的是非内核态的库不能添加到内核的目录下,不然编译和调试过程中相关的头文件可能找不到。在/vendor/厂商名/产品型号/config.json中的某一子系统下添加组件。

在 /build/lite/components/子系统名.json中添加组件,如下:

3. 编写配置BUILD.gn

移植的iperf3代码目录下需要提供一个gn文件,指明需要编译的代码。此文件可以通过import组件模板函数。一方面,很多引用到的头文件需要逐个添加到系统BUILD.GN中去,import组件模板函数可以省去很多麻烦;另一方面,头文件有多个,最终还很难确定是哪一个,使用系统配置好的组件模板函数,可以自动匹配。

4. 程序启动入口:将三方库添加到shell命令

1) 内核态的shell功能不符合POSIX标准,仅供调试使用,本文特记录下其添加命令的方法,此方法分为静态和动态两种方式,添加方式如下:

① 命令源代码包含如下头文件

#include "shell.h"
#include "shcmd.h"

  

② 静态注册命令方式

第一步:调用SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook),在源文件最后增加这个调用即可。

第二步:在链接选项中添加链接该新增命令项参数。

即在kernel/liteos_a/tools/build/mk/liteos_tables_ldflags.mk中增加相应选项,SHELLCMD_ENTRY的第一个参数前加-u。

此方法添加的shell,在代码编译阶段就已编译进去了,其实现原理是利用了编译器的section特性(也是代码模块化的重要手段),将所有shell命令相关功能都放在一段连续的地址空间,将SHELLCMD_ENTRY宏一层层展开,即可得到下面原型。

LOS_HAL_TABLE_BEGIN(g_shellcmd, shellcmd); //段的起始tag
LOS_HAL_TABLE_END(g_shellcmdEnd, shellcmd); //段的结束tag
SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook)

  

如下是编译后生成的map文件中shell段的部分,可以观察到已经通过此方法加入的shell命令。

③ 动态注册命令方式

此类方式是在代码运行阶段动态的注册,osCmdReg本身是一个函数,在命令初始化的源代码增加此函数调用。

UINT32 osCmdReg(CmdT ype cmdType, CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc)

  

函数原型在/kernel/liteos_a/shell/full/src/base/shcmd.c 可以找到,基本原理是将动态注册的shell命令加入到动态shell命令链表空间。

2)用户态的shell不用手动添加

添加目标的方式为executable,将程序下载到目标板上,在/bin目录下找到可执行的文件,只要在串口助手中输入 ./bin/可执行文件名,内核即可动态加载可执行的文件(或者输入exec  /bin/可执行文件名)。

三、iperf3使用方式介绍

使用iperf3测试时必须将一台主机设置为客户端,一台主机设置为服务器。在Linux环境或者Windows或者OpenHarmony shell交互窗口输入iperf3 -h可以获取iperf3的帮助信息。以下介绍几种常见的使用方式:

1. iperf3测试TCP

在默认的情况下,iperf3客户端与指定的监听5201端口的iperf3服务器建立一个TCP会话。

服务端:iperf3 -s
客户端:iperf3 -c 服务器IP (默认测试10秒),使用t来设置测试时间,单位是秒。
例如:iperf3 -c 192.168.99.74 -t 20

  

运行结果如下:

2. iperf3测试UDP

iperf3测试UDP性能时,客户端可以指定UDP数据流的速率。客户端发送数据时,将根据客户端提供的速率计算数据报发送之间的时延。

客户端还可以指定发送数据报的大小。每个发送的数据报包含一个ID号,用来唯一标识报文,服务器端根据该ID号来确定数据报丢失和乱序。

当把UDP报文大小设置可以将整个报文放入IP层的包(packet)内时,那么UDP所测得的报文丢失数据即为IP层包的丢失数据,这提供了一个有效的测试包丢失情况的方法。

数据报传输延迟抖动(Jitter)的测试由服务器端完成,客户发送的报文数据包含有发送时间戳,服务器端根据该时间信息和接收到报文的时间戳来计算传输延迟抖动。传输延迟抖动反映传输过程中是否平滑。由于它是一个相对值,所以并不需要客户端和服务器端时间同步。测试过程如下:

服务端:iperf3 -s -p 6868  (设定服务端监听6868端口)
Liteos_A shell客户端:./bin/iperf3 -c 172.17.5.159 -p 6868 -u -b 100M

  

测试结果:

- Jitter(延时变化):用iperf3 UDP测试来量度

- 数据报丢失:用iperf3 UDP测试来量度

- 带宽:通过TCP测试来量度

3. 反向带宽测试

服务端使用的命令不变,客户端需要加上参数-R,在帮助信息中,可以看到-R的信息是run in reverse mode (server sends, client receives)

服务端:iperf3 -s -p 6868
客户端:./bin/iperf3 -c 172.17.5.159 -p 6868 -u -b 100M -R

  

测试结果如下:

4. 同步双向带宽

测试

客户端加上命令参数 -bidir

服务端:iperf3 -s -p 6868
客户端:./bin/iperf3 -c 172.17.5.159 -p 6868 -u -b 100M -bidir

  

测试结果如下:

四、注意事项和遇到的问题及解决方法

1. Hi3516有三种下载程序的方式:串口、USB、网口转USB。推荐使用USB来下载程序,使用串口来调试程序。

2. DevEco Device Tool工具使用USB烧录Hi3516DV300镜像时失败,怎么解决?

解决措施:

出现这个问题,主要是因为开发者将Device Tool工具安装在系统盘符,在烧录大文件时会因为没有权限导致失败,可以根据以下操作解决:

● 在Windows平台找到安装目录,如图。鼠标右键,选中属性。

● 依次操作,步骤5将红框中两个选项都勾选上。

3. Hi3516如果携带操作系统是支持Linux内核的OpenHarmony,第一次下载时,需要格式化,下载完成后,系统启动到boot,就不会引导整个系统应用程序,这时需要点击如下菜单,然后重新拔插USB才能进入整个系统。

4. 在编写.gn文件时,如果三方组件为executable,那么第三方库代码中需要有唯一个入口main函数,最终生成一个可执行的命令。

5. iperf有大版本1,2,3,目前最新的是iperf3,不同的版本间命令参数不同,工作机制有所不同,所以在测试时,服务端和客户端要求使用相同的大版本。例如iperf3服务端不支持iperf的-u,-命令。

6. 在使用iperf3进行测试过程中,需要关闭防火墙,不然可能不能进行正常测试,可以提前使用ping测试一下网络是否已通。

7. 公司网络端的控制也会对测试造成影响,如果测试中发现发送和接收到的数据一直是0,则可能是网络控制端进行了控制,在拔掉外网络的情况,测试出来的结果就会很稳定。

8. Hi3516主板作为服务端,输入iperf3 -s,然后在PC机上启动客户端进行测试,发现根本不能进行正常测试,原因也是公司网络控制导致,解决办法是将要测试的两个网络接口,接到同一交换机下,然后拔掉外网的网线,可以进行正常测试;或者需要IT开发权限,当然如果不是在公司特定网络环境下,这个现象是不会出现的。

9. Hi3516需要设置网络才能进行测试,可以使用命令ifconfig来设置,例如:ifconfig eth0 172.17.5.253 netmask 255.255.254.0 gateway 172.17.4.1

10. MSS在OpenHarmony的底层LWIP不支持,在iperf_connect函数中调用getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len),会通过系统调用到达kernel层中的/kernel/liteos_a/compat/posix/src/socket.c, 最终走到底层LWIP的lwip_getsockopt_impl接口,在level IPPROTO_TCP下,对于分支TCP_MAXSEG,没有实现,解决办法是先屏蔽iperf3对此处的操作。同样在调用setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt))时,SO_SNDBUF分支在LWIP也未实现,先屏蔽此处,将发送缓冲区设置成和接收缓冲区同样的大小。

11. Liteos_A未实现延时删除,所以调用unlink时会出错,目前处理是先屏蔽此处。

12. Liteos_A对fprintf的实现也不如Linux,Windows好,所以对help命令输出到stdout上,长字串显示不出来,解决办法是使用fputs替换fprintf。

五、总结

本文从iperf3的工作原理、移植过程、使用方式、注意事项四个方面介绍了将iperf3移植到支持Liteos_A内核的OpenHarmony操作系统中的方法,希望本篇文章对开发者有所帮助。

关于OpenHarmony内核的内容,之前我还介绍了内核对象队列的算法、OpenHarmony LiteOS-M内核事件的运作机制,以及内核IPC机制数据结构,感兴趣的读者可以点击阅读:

OpenHarmony——内核对象队列之算法详解(上)》、

OpenHarmony——内核对象队列之算法详解(下)》、

OpenHarmony——内核对象事件之源码详解》、

OpenHarmony——内核IPC机制数据结构解析》。

OpenHarmony Liteos_A内核之iperf3移植心得的更多相关文章

  1. Linux内核3.0移植并基于Initramfs根文件系统启动

    Linux内核移植与启动 Target borad:FL2440 Bootloader:U-boot-2010.09 交叉编译器:buildroot-2012.08 1.linux内核基础知识 首先, ...

  2. linux内核链表的移植与使用

    一.  Linux内核链表为双向循环链表,和数据结构中所学链表类似,具体不再细讲.由于在内核中所实现的函数十分经典,所以移植出来方便后期应用程序中的使用. /********************* ...

  3. 小白自制Linux开发板 三. Linux内核与文件系统移植

    上一篇完成了uboot的移植,但是想要愉快的在开发板上玩耍还需要移植Linux内核和文件系统. 1.Linux内核 事实上对于F1C100S/F1C200S,Linux官方源码已经对licheepi ...

  4. Linux内核,文件系统移植过程中出现的一些问题与解决办法

    1.bootm地址和load address一样 此种情况下,bootm不会对uImage header后的zImage进行memory move的动作,而会直接go到entry point开始执行. ...

  5. Linux内核结构分析与移植

    Linux内核主要的5个部分是:进程调度,内存管理,虚拟文件系统,网络接口,进程通信. 这5个部分之间的关系如下: (1)进程调度部分负责控制进程对CPU的访问. (2)内存管理允许多个进程安全地共享 ...

  6. ANSIC程序到KeilC51的移植心得

    摘要:本文讲述了将ANSIC程序移植到KeilC51上应该注意的事项.文章讲述了存储类型.指针类型.重入函数.根据目标系统RAM的分布的段定位和仿真栈设置.函数指针.NULL指针问题.字节顺序.交叉汇 ...

  7. UCOS移植心得(

    移植UCOS之前,你首先应该做好三件事: 1.弄懂UCOS,这是谁都知道的哦 ^_^ 2. 弄懂你想要移植到的硬件平台 3. 清楚你使用的编译器是如何处理函数的局部变量和怎么样处理函数间的参数传递 这 ...

  8. uboot 、内核、文件系统移植

    1. 参考下面博客: http://blog.csdn.net/andylauren/article/details/51448353 2.查看u盘: $ sudo fdisk -l 3. 格式化u盘 ...

  9. android4.0.3源码之USB wifi移植心得

    http://blog.csdn.net/eastmoon502136/article/details/7850157 http://forum.cubietech.com/forum.php?mod ...

  10. 鸿蒙内核源码分析(根文件系统) | 先挂到`/`上的文件系统 | 百篇博客分析OpenHarmony源码 | v66.01

    百篇博客系列篇.本篇为: v66.xx 鸿蒙内核源码分析(根文件系统) | 先挂到/上的文件系统 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说一 ...

随机推荐

  1. matplotlib画图中x轴过于密集的解决办法

    import matplotlib.ticker as ticker ax.xaxis.set_major_locator(ticker.MultipleLocator(base=10)) # tic ...

  2. git 多系统复用账号

    重装系统前请备份~/.ssh下的公钥私钥文件,重装系统后,请使用以下方法复用好之前的key 将备份好的key copy至~/.ssh下 将私钥id_rsa的文件属性改为600:sudo chmod 6 ...

  3. Cocos Creator 2.x升级至Cocos Creator 3.x

    1.导入类时,批量导入 2.导入 override...关键字时,批量导入 3.this.node.scale = 0.6-->this.node.setScale(0.6, 0.6); 4.n ...

  4. javascript浮点数相减、相乘出现一长串小数

    149.7 * 100 = 14969.999999999998 3.57 - 2.33 = 1.2399999999999998 这是JavaScript浮点运算采用IEEE 754标准导致的Bug ...

  5. 【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数

    问题描述 在Azure App Service for Windows的环境中,部署.NET应用,其中使用了 SAP NetWeaver RFC函数 (需要加载 sapnwrfc.dll).详细的错误 ...

  6. 【Azure API 管理】API Management service (APIM) 如何实现禁止外网访问

    问题描述 API Management service 设置禁止外网访问,请求通过外网(Internet)将无法解析到APIM的网关地址,只能通过APIM所集成的内网(Virtual Network) ...

  7. kafka 为什么能那么快?高效读写数据,原来是这样做到的

    1. 利用 Partition 实现并行处理 我们都知道 Kafka 是一个 Pub-Sub 的消息系统,无论是发布还是订阅,都要指定 Topic. Topic 只是一个逻辑的概念.每个 Topic ...

  8. Java面向对象(下)--static/final/代码块/抽象/接口/内部类

    目录 1 关键字:static 2 理解main方法的语法 3 类的成员之四:代码块 4关键字:final 5 抽象类与抽象方法 6 接口(interface) 7 类的成员之五:内部类 static ...

  9. Zabbix与乐维监控对比分析(四)——告警管理篇

    在前面发布的Zabbix与乐维监控对比分析文章中,我们评析了二者在架构与性能.Agent管理.自动发现.权限管理.对象管理等方面的差异.接下来让我们一起看看二者在告警管理方面的差异. 告警管理是所有I ...

  10. KEIL5新建工程0810

    在保存各种项目的文件夹内创建一个项目文件夹1新建工程到文件夹1 选择芯片添加工程的必要文件(固件库) STM32程序是从启动文件开始,复制这些文件到文件夹A的新建Start文件夹下 stm32f10x ...