Jan 20, 2024
本文阅读量次WiFi无缝漫游详解 # 1、WLAN漫游简介 # 百度百科::当网络环境存在多个相同SSID的AP,且它们的覆盖范围的重合时,无线用户可以在整个WLAN覆盖区内移动,无线网卡能够自动发现附近信号强度最大的AP,并通过这个AP收发数据,保持不间断的网络连接,这就称为无线漫游。
简单来说:WLAN漫游是指STA在不同的AP覆盖范围之间移动,且保持用户业务不中断的行为。
AP:也就是无线接入点,是一个无线网络的创建者,是网络的中心节点。一般家庭或办公室使用的无线路由器就一个AP。 STA:每一个连接到无线网络中的终端(如笔记本电脑、PDA及其它可以联网的用户设备)都可称为一个站点。 如下图所示,STA1从AP1的覆盖范围移动到AP2的覆盖范围时保持业务不中断。
2、WiFi漫游由来 # 当家庭面积超过一定面积后,为了保证全家范围的wifi网络覆盖,我们就需要引入2个以上的WiFi接入点了。在多个WiFi接入点下,为了优化网络使用体验,免去手动切换wifi接入的麻烦,就需要引入WiFi漫游。
伪漫游: 一般最常见的伪漫游方法就是将2个以上的wifi接入点的SSID名称及密码设置相同,虽然起到了一定的切换作用,不过用过的朋友都知道效果非常的不好,先不说能否自动切换的问题,就算切换成功了,也会造成IP地址的改变,游戏掉网、断连接是必须的!因此在多AP情况下就必须引入一个新的名词:Wifi快速漫游
WiFi漫游 上文提到的设置SSID名称及密码相同的方案是最低能的做法,稍微懂一点网络知识的朋友都不会采用的;
最次的方案也是要保证DHCP服务器的统一,保证切换Wifi时候IP地址不变。
更进一阶,引入AC控制器,利用AC+AP的组合形式实现wifi漫游。目前市面上主流的TPlink、爱快、Mesh等产品的方案多是如此。
其根本的原理是通过AC设定AP的RSSI阈值,将信号不稳定的设备T下线,迫使终端设备重新连接信号最强的AP,实现AP的自动切换。
实话实说这种方案对于绝大多数的用户是完全够用的,AP切换过程中网络中断时间一般在200ms-500ms左右,影响不大,确实优化了网络体验。对于网络要求不高的朋友推荐选择。不过在该方案下游戏会有一段明显的卡顿,但不会掉线。
WiFi快速漫游 如果你是一个追求完美网络体验的朋友,而且想一次到位部署网络,不再折腾了,那么你就需要Wifi快速漫游了。上面介绍的第二种方案,虽然效果说得过去,但仍然无法保证切换过程尽可能的少丢包及进一步缩短网络中断时间。这个时候就必须引入Wifi快速漫游方案了,通过Wifi快速漫游进一步缩短网络中断时间,提高网络使用体验,真正实现游戏中不卡顿
对于有AC控制器的Wifi网络系统中,漫游过程可以简单分为3个阶段:漫游触发→选择新AP→重新认证。这时候就需要802.11k/v/r协议登场了。
由于Wifi网络密码的存在,在重新认证阶段终端在切换AP的时候需要出示其缓存的密钥,AP检查密钥并进行四次握手,产生数据加密密钥,漫游完成。802.11r协议可以在以上基础上省略4次握手,进一步缩减了断网的时间。 802.11k能告诉终端,如何快速选择漫游AP。 802.11v能优化漫游触发。 能够应用802.11k/v/r协议的Wifi漫游都可以称之为快速漫游,不过这需要AP和终端都支持哦,实际上目前能够支持802.11k/v/r协议的终端并不多,苹果算是一个例外吧,新产品全都支持802.11k/v/r,所以Wifi快速漫游更适合使用苹果的土豪们
综上,WLAN漫游策略主要解决以下问题:
避免漫游过程中的认证时间过长导致丢包甚至业务中断:802.1x认证、Portal认证等认证过程报文交互次数和时间,大于WLAN连接过程,所以漫游需要避免重新认证授权及密钥协商过程。 保证用户授权信息不变:用户的认证和授权信息,是用户访问网络的通行证,如果需要漫游后业务不中断,必须确保用户在AC上的认证和授权信息不变 保证用户IP地址不变:应用层协议均以IP地址和TCP/UDP Session为用户业务承载,漫游后的用户必须能够保持原IP地址不变,对应的TCP/UDP Session才能不中断,应用层数据才能够保持正常转发 3、漫游基础知识 # WLAN漫游的网络架构
AC控制器:可用来集中化控制和管理无线AP,是一个无线网络的核心,负责管理无线网络中的所有无线AP,对AP管理包括:下发配置、修改相关配置参数、射频智能管理、接入安全控制等。 漫游组:在WLAN网络中,可以对不同的AC进行分组,STA可以在同一个组的AC间进行漫游,这个组就叫漫游组。如图,AC1和AC2组成一个漫游组。 AC间隧道:为了支持AC间漫游,漫游组内的所有AC需要同步每个AC管理的STA和AP设备信息,因此在AC间建立一条隧道作为数据同步和报文转发的通道。 Master Controller:STA在同一个漫游组内的AC间进行漫游,需要漫游组内的AC能够试别组内其他AC。通过选定一个AC作为Master Controller,在该AC上维护漫游组成员表,并下发到漫游组内AC,使各AC之间相互试别并建立AC间隧道,如图,选的AC1作为Master Controller. Master Controller既可以是漫游组外的AC,也可以在漫游组内选择一个AC Master Controlle管理其他AC的同时,不能被其他Master Controlle管理 AC内漫游:如果漫游过程中关联的是同一个AC,则是AC内漫游,如图STA从AP1漫游到AP2即是AC内漫游 AC间漫游:如果漫游过程中关联的不是同一个AC,则是AC间漫游,如图STA在从Ap1漫游到AP3的过程即为AC间漫游 HAC (Home AC):STA首次与漫游组内某个AC进行关联,则该AC为它的HAC HAP (Home AP):STA首次与漫游组内某个AP进行关联,则该AP为它的HAP FAC(Foreign AC):STA漫游后关联的AC即为它的FAC FAP(Foreign AP):STA漫游后关联的AP即为它的FAP 4、漫游的分类 # 漫游根据实际的架构我们将它分为两类:有缝漫游和无缝漫游。无缝漫游又可以分为二层漫游和三层漫游。
有缝漫游:有两种情况
所有网络部署的AP是胖AP,没有AC。 所有网络部署的AP是瘦AP,没有AC也可以工作。 胖瘦AP的区别:https://zhuanlan.zhihu.com/p/64648479
上面两种情况,主要是我们国情产生的,客户不停的压价还要一大堆需要。大家为了降低成本,没有部署AC。只需要SSID、加密配置和信道岔开即可。实际效果第中远好于第一种,因为第二种是在一个DHCP下,第一种就相当安装了很多的家用路由器,问题多多!
无缝漫游:
...
Jan 20, 2024
本文阅读量次【一文秒懂】Linux调试工具——GDB介绍 # 1、GDB是什么 # GDB:GNU Project Debugger是GNU工程仿真器,允许开发者能够去看程序内部发生的情况,或者发生crash时候, 知道程序正在做什么!它诞生于 GNU 计划(同时诞生的还有 GCC、Emacs 等),是 Linux 下常用的程序调试器。发展至今,GDB 已经迭代了诸多个版本,当下的 GDB 支持调试多种编程语言编写的程序,包括 C、C++、Go、Objective-C、OpenCL、Ada 等。实际场景中,GDB 更常用来调试 C 和 C++ 程序。
GDB主要功能有四个方面:
启动程序:指定任何可以影响其运行行为的动作 停止程序:使程序在指定条件下停止 检查错误:当程序停止时,检查发生了什么 纠正错误:更改程序中的内容,纠正错误 GDB可以在本地、远程、仿真器上执行。
2、GDB如何使用 # 如何使用GDB?
要想回答这个问题,从正统角度来分析,有两种方式:
GDB官方手册:https://sourceware.org/gdb/
GDB帮助信息:help all(命令行输入)
简单来说,GDB调试方法有3种:
直接调试:gdb [exec file],用于直接仿真一个执行程序 附属调试:gdb attach pid,用于直接调试一个已运行的程序(ubuntu注意权限问题) 核心转存调试:gdb [exec file] [core-dump file],用于调试core-dump文件 Tips:GDB调试的[exec file],该文件最好编译的时候带上-g选项,生成带调试信息的可执行文件。
3、GDB常用指令 # 3.1 基础指令 # 指令 含义 file [exec file] 选择要调试的可执行文件 run/r 重新开始运行文件 start 暂时断点,停在第一执行语句处 list/l 查看源代码 next/n 单步调试,逐过程,函数直接执行 step/s 单步调试,逐语句,跳入函数执行 backtrace/bt 查看函数调用的堆栈信息 finish 结束当前函数,返回函数调用点 continue 继续执行 print/p 打印变量 break/b [filename:line_number] 打断点, [文件名:行号],也有多种方式 quit 退出gdb调试 3.
...
Jan 20, 2024
本文阅读量次【一文秒懂】Linux远程调试工具——gdbserver # 1、介绍 # 对于开发者来说,调试必不可少。
对于开发PC软件,通常系统已经继承了调试工具(比如Linux系统的GDB),或者IDE直接支持对程序的调试。
而对于开发嵌入式软件来说调试的手段比较有限,很多开发者仅有的调试手段依然是最原始的打印(我也是其中之一)。
当然除了打印调试之外还有通过gdb+gdbserver来调试,gdbserver在目标系统中运行,gdb则在宿主机上运行。
简而言之,gdbserver 是一个程序,它允许宿主机可以通过网络,远程调试目标板。
2、如何使用 # 2.1 编译器准备 # 这里就不再详细讲解编译器的安装什么的了,网上一大把!
#直接安装 sudo apt-get install gcc-arm-linux-gnueabihf #源码安装 $ tar zxvf gdb-7.12.tar.gz $ cd gdb-7.12/ $ ./configure --target=arm-linux --prefix=$PWD/__install $ make $ make install 编译完成后,最终会生成gdbserver 的可执行程序,这个就是我们要使用的工具。
2.2 目标机准备 # 我们将gdb_server可执行程序放置目标板上。 再将我们要调试的程序放置目标板上,如helloworld 使用gdb_server进行调试,使用方法如下: gdbserver 192.168.xx.xx:1234 ./helloworld 192.168.xx.xx:IP地址信息
1234:自定义端口号
./helloworld:运行要仿真的程序
此时gdbserver监听端口号1234,并等待客户端连接。
2.3 宿主机准备 # 在宿主机(Ubuntu)上,使用gdb调试 远程连接目标机 运行程序 $ gdb (gdb) target remote 192.168.xx.xx:1234 Remote debugging using :1234 c #运行 target remote:远程连接到指定IP的端口
...
Jan 20, 2024
本文阅读量次【一文秒懂】Linux内核死锁检测 # 最近遇到了一个驱动上面的BUG,导致终端敲命令都无响应,最终导致内核触发了hung_task_timeout…
为什么会出现这种情况?该如何排查?
1、死锁 # 死锁指两个或更多进程或线程因相互等待对方释放资源而互相阻塞,从而导致系统中所有的进程或线程都无法继续运行的情况。
一个典型的死锁场景包括以下几个角色:
资源:系统内的某个文件、某个设备、共享的内存区域等。 进程/线程:进程或线程需要访问某个资源来完成其工作,但其当前无法取得该资源的控制权,因为该资源已被其他进程或线程占用。 饥饿:由于进程无法获取其需要的资源,它不能继续前进或完成操作。如果没有正确的措施来处理和解决死锁,进程可能会一直等待,直到设备或整个系统崩溃。 2、常见的死锁方式 # 常见死锁的2种方式:
AA锁:包括重复上锁和上下文切换引起的上锁,即一个线程,持有A锁,还未释放,又去请求A锁 AB-BA死锁:一个F1线程,持有A锁,再去获取B锁,而一个F2线程持有B锁,再去获取A锁,这个时候处于的死锁状态 常见的死锁有以下4种情况:
进程重复申请同一个锁,称为AA死锁。例如,重复申请同一个自旋锁;使用读写锁,第一次申请读锁,第二次申请写锁。 进程申请自旋锁时没有禁止硬中断,进程获取自旋锁以后,硬中断抢占,申请同一个自旋锁。这种AA死锁很隐蔽,人工审查很难发现。 两个进程都要获取锁L1和L2,进程1持有锁L1,再去获取锁L2,如果这个时候进程2持有锁L2并且正在尝试获取锁L1,那么进程1和进程2就会死锁,称为AB-BA死锁。 在一个处理器上进程1持有锁L1,再去获取锁L2,在另一个处理器上进程2持有锁L2,硬中断抢占进程2以后获取锁L1。这种AB-BA死锁很隐蔽,人工审查很难发现。 内核提供了Lockdep来检测死锁的异常情况
3、Lockdep 内核配置 # CONFIG_LOCKDEP: CONFIG_DEBUG_LOCK_ALLOC:检查内核是否错误地释放被持有的锁。 CONFIG_PROVE_LOCKING:允许内核报告死锁问题。 CONFIG_DEBUG_LOCKDEP :在死锁发生,内核报告相应的死锁 CONFIG_LOCK_STAT:追踪锁竞争的点,解释的更详细 4、Lockdep 初探 # lockdep操作的基本单元并非单个的锁实例,而是锁类(lock-class)。比如,struct inode结构体中的自旋锁i_lock字段就代表了这一类锁,而具体每个inode节点的锁只是该类锁中的一个实例。对所有这些实例,lockdep会把它们当作一个整体做处理,即把判断粒度放大,否则对可能有成千上万个的实例进行逐一判断,那处理难度可想而知,而且也没有必要. lockdep跟踪每个锁类的自身状态,也跟踪各个锁类之间的依赖关系,通过一系列的验证规则,以确保锁类状态和锁类之间的依赖总是正确的。另外,锁类一旦在初次使用时被注册,那么后续就会一直存在,所有它的具体实例都会关联到它。 锁的几个状态:
ever held in STATE context –> 该锁曾在STATE上下文被持有过 ever head as readlock in STATE context –> 该锁曾在STATE上下文被以读锁形式持有过 ever head with STATE enabled –> 该锁曾在启用STATE的情况下被持有过 ever head as readlock with STATE enabled –> 该锁曾在启用STATE的情况下被以读锁形式持有过 5、Lockdep 检查规则 # 单锁状态规则如下: (1)一个软中断不安全的锁类也是硬中断不安全的锁类。
...
Jan 20, 2024
本文阅读量次我的圈子: 高级工程师聚集地 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 亲爱的读者,你好: 感谢你对我的专栏的关注和支持,我很高兴能和你分享我的知识和经验。如果你喜欢我的内容,想要阅读更多的精彩技术文章,可以扫码加入我的社群。
欢迎关注【嵌入式艺术】,董哥原创!
Jan 20, 2024
本文阅读量次我的圈子: 高级工程师聚集地 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 亲爱的读者,你好: 感谢你对我的专栏的关注和支持,我很高兴能和你分享我的知识和经验。如果你喜欢我的内容,想要阅读更多的精彩技术文章,可以扫码加入我的社群。
欢迎关注【嵌入式艺术】,董哥原创!
Jan 20, 2024
本文阅读量次【一文秒懂】Linux内核态内存泄露检测工具 # 1、Kmemleak介绍 # 在Linux内核开发中,Kmemleak是一种用于检测内核中内存泄漏的工具。
内存泄漏指的是程序中已经不再使用的内存没有被妥善地释放,导致内存的浪费。内核中的内存泄漏同样会导致系统性能下降、系统崩溃等问题。
Kmemleak能够检测内核中的内存泄漏,通过检测内核中未被释放但又无法找到其使用位置的内存,进一步定位、修复内存泄漏的问题。
在用户空间,我们常用Valgrind来检测;
在内核空间,我们常用Kmemleak来检测。
2、如何使用Kmemleak # 2.1 内核配置 # 内核打开相应配置:
CONFIG_DEBUG_KMEMLEAK:Kmemleak被加入到内核 CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE设置为16000:该参数为记录内存泄露信息的内存池,越大记录信息越多。 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF :Kmemleak默认开关状态 依赖的配置:
CONFIG_DEBUG_KERNEL:打开内核调试功能 CONFIG_DEBUG_FS:需要借助到debugfs CONFIG_STACKTRACE:记录进程的堆栈信息 2.2 用户空间配置 # 我们要想使用Kmemleak,需要挂在debugfs,来查看泄露的情况。
进入文件系统后,进行挂载: mount -t debugfs nodev /sys/kernel/debug/ # 挂在debugfs 设置扫描时间: echo scan=10 > /sys/kernel/debug/kmemleak # 10S扫描一次 默认内存泄露检测时间为10min,上面设置为10s一次
查看泄露情况: cat /sys/kernel/debug/kmemleak # 查看内存泄露情况 其他指令: echo scan > /sys/kernel/debug/kmemleak #触发一次扫描 echo clear > /sys/kernel/debug/kmemleak #清除当前 kmemleak 记录的泄露信息 echo off > /sys/kernel/debug/kmemleak #关闭kmemleak(不可逆转的) echo stack=off > /sys/kernel/debug/kmemleak #关闭任务栈扫描 echo stack=on > /sys/kernel/debug/kmemleak #使能任务栈扫描 echo scan=on > /sys/kernel/debug/kmemleak #启动自动内存扫描线程 echo scan=off > /sys/kernel/debug/kmemleak #停止自动内存扫描线程 echo scan=<secs> > /sys/kernel/debug/kmemleak#设置自动扫描线程扫描间隔,默认是600,设置0则是停止扫描 echo dump=<addr> > /sys/kernel/debug/kmemleak #dump某个地址的内存块信息,比如上面的echo dump=0xffffffc008efd200 > /sys/kernel/debug/kmemleak即可查看详细信息 2.
...