查看程序信息
bash
ulimit -c unlimited #记录 core
top -Hp pid #查询进程pid每个线程的CPU占比
ps p [pid] -L -o pcpu,pid,tid,time,tname,stat,psr |sort -n -k1 -r #查看进程内线程CPU占用率,包含tid
pstack [pid] #查看进程内线程调用栈,可用上一步查到的tid做匹配
top -d 1 #间隔1秒刷新top
# 查看静态库版本
strings libexample.a | grep '[0-9]\+\.[0-9]\+\.[0-9]\+'
# 查看动态库导出函数
readelf -s libyangh264dec.so
# 查询程序依赖库
ldd exe
perf查看热点函数
bash
# 查看指定进程的热点函数,加选项-g生成热点函数调用栈
perf top -p 3593
# 生成火焰图
perf record -F 180 -p 3593 -g -- sleep 120
# 当前目录生成 perf.data 文件
arm编译perf参考:arm平台常用工具和动态库编译
ubuntu 安装 perf
bash
# ubuntu 安装 perf
sudo apt-get install linux-tools-common
报错 :
WARNING: perf not found for kernel 5.15.0-116
You may need to install the following packages for this specific kernel:
linux-tools-5.15.0-116-generic
linux-cloud-tools-5.15.0-116-generic
# 安装对应版本内核工具
sudo apt-get install linux-tools-5.15.0-116-generic
# 查询perf版本
perf -v
查看系统实时性能
sysstat工具包
bash
sar -n DEV 1 #网卡测速,1秒一次
mpstat -P ALL #查看每个cpu占比,zynq和arm均可用
mpstat -P ALL 1 100 #所有CPU每1秒采样一次,共采样100次,结束后打印平均值
mpstat -P 0 1 10 #只采样0号CPU,每1秒采样一次,共采样100次,结束后打印平均值
# 显示参数 描述
# CPU 显示的是某个CPU 还是全部CPU all=全部
# %usr 表示用户所有使用的CPU百分比,比如程序中while死循环,则usr占比100%
# %nice 表示使用 nice 值的 CPU 的百分比。
# %sys 表示内核进程使用的 CPU 百分比。比如sendto等系统调用,死循环sendto则sys占比100%
# %iowait 表示等待进行 I/O 所使用的 CPU 时间百分比。
# %irq 表示用于处理系统中断的CPU百分比
# %soft 表示用于软件中断的CPU百分比
# %steal 虚拟机强制CPU等待的时间百分比
# %guest 虚拟机占用CPU时间的百分比
# %gnice CPU运行niced guest虚拟机所花费的时间百分比
# %idle CPU的空闲时间的百分比
查看系统运行信息
bash
# arm查进程状态
cat /proc/进程PID/status
# 查CPU信息
cat /proc/cpuinfo
# 查看系统总内存大小
cat /proc/meminfo | grep MemTotal
# 查看磁盘大小
lsblk
# 查询中断在哪个核上
cat /proc/interrupts
# 查询总内存,已使用内存,空闲内存等
free -h
# 打印进程中线程(线程ID,线程名,用户时间,内核时间)
awk '{print $1,$2,$14,$15}' /proc/2832/task/*/stat #*/
查看和设置网卡
bash
# 查询网卡信息
ethtool eth0
ethtool -i eth0
ifconfig eth1 promisc #设置混杂模式
ifconfig eth1 -promisc #取消混杂模式
ifconfig #输出包含 PROMISC 时,表明该网络接口处于混杂模式
mtu查询与设置
关于 mtu:
1、网卡mtu设置为1500,抓包最大长度1514,链路层长度14,IP头20,UDP头8,负载1472。
2、如果发的udp负载超过1472就会被网卡分包,因此udp发数据时不能只看网卡mtu,还要减去链路层、网络层、传输层的开销。
3、udp数据被发送端网卡分包,接收端网卡不会组包,会给接收端造成困难,因此udp负载不能太大。
4、tcp是数据流,通常不受mtu影响。
linux
bash
# 修改 mtu
# linux
ifconfig eth0 1600
# ubuntu永久修改mtu,网卡下面添加mtu: 2000
# 添加一个网卡并配置ip/网管/dns,开机会自启动网卡
vim /etc/netplan/00-installer-config.yaml
enp2s0:
dhcp4: true
mtu: 2000
enx00e04c3606cb:
dhcp4: false
addresses: [192.168.72.193/24]
gateway4: 192.168.72.1
nameservers:
addresses: [114.114.114.114,8.8.8.8]
arm系统,IP配置写入文件
bash
vi /etc/eth0-setting
IP=192.168.1.100
Mask=255.255.255.0
Gateway=192.168.1.1
DNS=192.168.1.1
MAC=d3:56:fa:a2:e0:05
windows
bash
# win
# 查询mtu
netsh interface ipv4 show subinterface
# 修改网卡mtu,管理员运行
netsh interface ipv4 set subinterface "以太网 2" mtu=1500 store=persistent
# 开启巨帧
网卡-属性-网络-配置-高级-巨型帧,默认关闭,可选择9014Bytes,如果配置里没有巨型帧选项,可使用驱动精灵升级网卡驱动。
iperf3测速
-s 以服务端启动
-p 指定监听断开
-B 服务端绑定IP,通常不用指定,因为iperf会自动监听所有IP
-i 间隔时间回显测试数据,单位秒,不设置该选项则默认1秒
-c 指定iperf3服务器的IP地址,客户端设置。
-u 表示使用UDP协议,不设置则默认tcp。
-b 指定测试使用的带宽,例如 -b 100M 表示100 Mbps,可控制发送速率。
-t 指定测试的时间,例如 -t 60 表示60秒。
-l 指定数据包的长度,例如 -l 1470 表示1470字节(以避免IP和UDP头部)。
bash
# iperf3 测试
# 服务端,同时监听tcp和udp,端口5205,默认监听所有IP
iperf3 -s -p 5205
# udp客户端
iperf3 -u -c 10.10.1.191 -p 5205 -b 1000M -t 60 -l 1300
抓包分析
linux抓包命令
bash
tcpdump -i eth0 -B 65535 -w eth0.pcap -vvv
wireshare 常用过滤规则
bash
frame.len == 1434 #按帧长过滤
udp.length < 30 #udp包长度过滤
ip.src_host == 192.168.1.114 #按源IP地址过滤
ip.dst_host == 192.168.1.114 #按目的IP地址过滤
ip.addr == 192.168.3.77 #按源或目的IP地址过滤
tcp.len == 1448 #tcp包长度等于1448(除去tcp及以上头部的数据部分长度)
tcp.port == 80 #按tcp端口过滤,包括源和目的端口,udp类似
tcp.dstport == 80 #按tcp目的端口过滤
tcp.srcport==80 #按tcp源端口过滤
eth.type == 0xfffc #自定义协议类型过滤
#标记:ctrl+C
#跳到下一个标记的数据包:ctrl+shift+N
#跳到上一个标记的数据包:ctrl+shift+B
termshark
一款带UI界面的可以在linux命令行抓包和查看包的软件,界面类似wireshark。
go语言开发,建议直接下载release版本:termshark_2.4.0_linux_x64.tar.gz。
https://github.com/gcla/termshark/releases
bash
# 通常需要安装依赖
sudo apt install tshark
# 压缩包只有可执行文件,拷贝到系统目录
sudo cp termshark /usr/local/bin/
# 抓取网卡包并保存
sudo termshark -i ens33 -w 11.pcap
# 打开包
sudo termshark 11.pcap
程序调试
调试命令
Clion:F7进入函数,F8单步调试,F9跳转到下个断点(也可以在 GDB 界面使用 gdb 命令行调试)。
Qt:F10单步调试,F11进入函数体,F5跳转到下个断点。
arm/zynq交叉编译gdb
交叉编译gdb源码,可以直接在arm上gdb调试,不需要远程调试。
bash
gdb
#gdb 查看core文件
gdb exe
core-file core.1882 #指定core文件
bt #查看crash调用栈
# gdb 进入调试正在运行的程序
gdb
attach [pid]
# gdb 调试运行
gdb exe
b UdpServer::start_l #在函数打断点
b UdpServer.cpp:180 #在文件的多少行打断点
b 250 #在当前调试文件的第250行打断点,刚启动时默认在main函数所在文件
i b #查看断点
r 1 #运行,1是参数,遇断点停留
l #查看源码(list)
n #单步调试
s #进入函数体
c #跳转到下个断点
d 1 #删除第一个断点
p #打印变量
q #退出gdb
finish #返回当前函数,打印返回值
winheight #窗口化调试
gdb 调试arm
b main #打断点
i b #查断点
c #运行至下一个断点
p i #打印变量
info threads #展示线程列表
thread 2 #切换到2号线程
bt #打印线程调用栈
q #退出gdb