首页 > > > 调试Linux Kernel任意模块
最近因为遇到一件很反常识的事情:TCP能够稳定发包却没有丢包的现象。直接读论文的话有点摸不着头脑,于是得直接拿内核代码tcp_cubic.c调了。
比如我需要调节的模块为/net/ipv4/tcp_cubic.c(本文不做任何说明都以该模块为例)。
首先确认是动态加载(写入了内核镜像,obj-y)还是编译成模块(obj-m)。
首先在/net/ipv4/Makefile中找到配置的名称CONFIG_TCP_CONG_CUBIC。
之后使用cat /boot/config-$(uname -r) | grep "CONFIG_TCP_CONG_CUBIC"
得到:CONFIG_TCP_CONG_CUBIC=y
发现是被编译到了内核镜像中,必须重新编译整个内核文件获取新的镜像。如果是=m那么直接卸载相应的模块,不需要重新编译整个内核[1]。
首先根据自己的需求下载相关版本的内核代码。
编译内核的步骤可以参考:
在Ubuntu 18.04上编译Linux内核
为了便于后面的调试,我们将CONFIG_TCP_CONG_CUBIC=y改为CONFIG_TCP_CONG_CUBIC=m。并且我们也不需要使用menuconfig进行配置。
#将下载好的内核代码解压好,放在/usr/src文件夹下,进入该文件夹,以5.0.10为例
#配置环境
sudo apt-get install gcc make libncurses5-dev openssl libssl-dev
sudo apt-get install build-essential
sudo apt-get install pkg-config
sudo apt-get install libc6-dev
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libelf-dev
# 修改相关的配置=y改成=m
sudo cp /boot/config-$(uname -r) .config
sudo vim .config
sudo make -j4 #开启多核编译,加快编译速度
sudo make modules_install
sudo make install
sudo mkinitramfs -o /boot/initrd.img-5.0.10
sudo update-initramfs -c -k 5.0.10
sudo update-grub2
# 检验结果
sudo shutdown -r now
uname -a可能会使用下面的命令:
sudo insmod tcp_cubic.c
sudo rmmod tcp_cubic #若显示in use只能重启,因为没有写入开机自动加载的脚本中,所以开机后不会加载
dmesgdmesg可能会有这样的提示:
[20547.991461] tcp_cubic: loading out-of-tree module taints kernel.
[20548.003909] tcp_cubic: module verification failed: signature and/or required key missing - tainting kernel说明血统不够纯正[2],但是还是能加载使用(雾
比如现在需要触发tcp_cubic.c该模块,需要进行下面的设置[3]:
sysctl net.ipv4.tcp_available_congestion_control #查看发现无cubic模块
sudo vim /proc/sys/net/ipv4/tcp_congestion_control #bbr改为cubic
sudo sysctl -p /proc/sys/net/ipv4/tcp_congestion_control #重新加载配置文件,或ldconfig使用printk()进行调试:printk(KERN_DEBUG "INFO");,信息可以使用dmesg显示。
于是就可以开(zi)心(bi)的调试代码了。
TCP协议中需要特别注意的两个参数ssthresh和cwnd。
为什么反常识呢?因为我们学习到的TCP拥塞控制算法,在遇到丢包这个时间后,才会收敛,降低拥塞控制窗口。
如reno算法:
若cwnd<ssthresh: cwnd会每收到一个ack, cwnd=cwnd+1;
若cwnd>ssthresh: cwnd会每个RTT时间窗口+1
若丢包:
ssthresh直接减半[4],若有快恢复的设置,此时cwnd=减半后的sstresh; 更古老的版本当然是sstresh=1。
在上面古老的认知[5][6]中,可见ssthresh一丢包才减小,并且是始终减小的。cwnd也是丢包了才减小,不然一直增加[7]。
在上面的认知范围中,确实TCP不可能能够不丢包然后平稳的发送数据。但是现在都<手动删除线>0202<手动删除线>年了,需要更新我们的认知体系了。
不丢包就能稳定发送有下面的三个方面控制:
ssthresh=0x7fffffff,然后丢包后每次折半,直到找到合适的值。这个过程需要进行大量的丢包。目前内核中一个叫hystart[8]的优化,具体的原理可以读相关的paper。大概的思路:ssthresh,能够不用丢包就能较准确的估计。cubic使用(慢启动+hystart)代替传统的慢启动。In this section we describe our slow start algorithm, called HyStart that reduces burst packet losses during slow start and hence achieves better throughput and a lower system load.
2. RFC 2861[9]文档中提到,若上层应用受到了限速,那么发送的数据包将会明显的小于此时的cwnd,因此此刻的cwnd不能准确控制应用层的发送速率。于是,若发送的间隔超过一个RTO,我们需要及时的降低cwnd。这也就是为什么在不丢包的情况下,能够减小cwnd。并且满足一定情况下,还能够增加ssthresh, 。
3. 如果当前窗口利用率小于50%,
这样,你就能准确的解释debug_info.txt中的数据变化了。
Linux在某一次演讲时与观众互动,其中一位女生想知道linux与N卡的兼容性问题,遂出现了这一幕
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/758/viewspace-3132420/ ,如需转载,请注明出处,否则将追究法律责任。