2024年1月21日发(作者:)
VxWorks常用的命令
1.与任务相关的命令
sp function,[arg1],...,[arg9]
-启动任务,最多接受9个参数,默认的优先级100、堆栈20000字节
period n,function,[arg1],...,[arg8]
-创建一个周期调用function的任务,周期为n秒,最多接受8个参数
repeat m,function,[arg1],...,[arg8]
-创建一个反复调用function的任务,调用次数为m,m=0时永久调用,最多也是8个参数
ts tidX -挂起任务
tr tidX -恢复挂起的任务
td tidX -删除任务
i tidX -显示任务基本信息,参数为0时显示全部任务
ti tidX -显示任务详细信息,包括寄存器、堆栈等
tt tidX -显示任务的函数调用关系
checkStack tidX -显示任务堆栈使用的历史统计,参数为0时显示全部任务
[其中tidX可以为任务ID 也可以为任务名]
2、系统信息
lkup ["string"] -在系统符号表中查找并列出含有"string"字符的函数及全局变量,有两个特殊参数:
0,给出符号表统计;""(空字符串),列出全部符号
lkAddr addr -显示addr地址附近的符号表
l addr,[n] -显示addr地址开始的n条指令的反汇编,n省略时默认为10条指令
h [n] -n为0时列出最近执行的shell命令,默认20条;n非0时,设定shell记录的历史命令的数目
d [addr,[number],[width]]
-显示addr地址开始的number个单元的内容,width定制每个单元的宽度,可以是1、2、4、8
m addr,[width] -按width宽度修改addr地址的内容,width可以是1、2、4、8
memShow 1 -显示系统分区上空闲和已分配空间的总数等
printErrno value -打印系统定义的错误码的宏
3、与网络相关的命令
ifShow ["ifname"] - show info about network interfaces
inetstatShow - show all Internet protocol sockets
tcpstatShow - show statistics for TCP
udpstatShow - show statistics for UDP
ipstatShow - show statistics for IP
icmpstatShow - show statistics for ICMP
arpShow - show a list of known ARP entries
mbufShow - show network stack data pool statistics
netStackSysPoolShow - show network stack system pool statistics
routeShow - display all IP routes (summary information)
mRouteShow - display all IP routes (verbose information)
routestatShow - display routing statistics
routeAdd "destaddr","gateaddr" - add route to route table
routeDelete "destaddr","gateaddr" - delete route from route table
说明:上述大多数命令都可以在help、netHelp中查到
vxWorks命令规则:名词+动词,第二个单词开始大写
序号 状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
BSP
BSP
BSP
BSP
BSP
BSP
命令
c
p
@
ctrl+x
备注
改变配置
打印当前配置信息
开始加载内核
重新启动
vxWorks i
vxWorks ifShow
vxWorks devs
vxWorks cd "/xxx/"
vxWorks cfIdeInit
vxWorks cfFormat
vxWorks ll
vxWorks ls
vxWorks version
vxWorks td xxx
vxWorks help
vxWorks tffsShow
vxWorks tffsDevFormat
vxWorks showTime
查看进程
查看当前网络设置
查看所有的设备
进入目录
每次上电后执行
新卡(或者是未格式化的卡)插入的时候执行,只需执行一次
以详细模式查看当前目录下的文件
以简单模式查看当前目录下的文件
查看编译时间
终止xxx进程
帮助
查看tffs的相关信息
格式化tffs文件系统
查看系统时间
21
22
23
24
25
vxWorks usrTffsConfig(0,0,"/tffs0")
vxWorks pwd
vxWorks ping "",10,0
vxWorks pciDeviceShow
vxWorks pciHeaderShow,0,xx
新增一个tffs格式的文件系统
查看当前操作所在的目录路径
ping地址,共计10次
查看当前系统中的所有PCI设备
查看当前系统中的组号为0、地址号为xx的PCI设备
VxWorks任务追踪实例分析
VxWorks中如果稍有不慎,就可能导致task suspend,如果运气好,shell没有被挂起,则可以通过系统的一些命令追踪一下挂起的原因。其中用到的主要命令是i、tt、ti、d等。
首先从出错信息开始:
0xfc8125b8 (t_Lcd): memPartFree: invalid block 0xfdfc6f38 in partition
0xfe508894.
由于memPartFree了一个非法的内存块,导致了任务挂起,我们需要确定到底是哪条语句导致了这个异常的产生,可能是什么原因引起的。
首先,需要通过“i”命令察看任务状态:
-> i
NAME ENTRY TID PRI STATUS PC SP
ERRNO DELAY
---------- ------------ -------- --- ---------- -------- --------
------- -----
tExcTask excTask fdffec80 0 PEND fe3c5f50 fdffeb60
3006b 0
tLogTask logTask fdffc298 0 PEND fe3c5f50 fdffc188
0 0
tShell shell fdf5fa48 1 READY fe1f3afc fdf5f628
0 0
……
t_Lcd fe392a30 fc8125b8 100 SUSPEND fe1f24b0 fc8120b8
d0003 0
……
可以看到任务t_Lcd的状态为SUSPEND,即被挂起的状态。其他各项的含义都比较清楚,ENTRY是任务的入口函数,如果没有symbol,则直接显示地址,TID是任务的ID号,一般用任务的栈底地址表示,PC是当前的指令位置,SP是当前栈顶位置。
然后通过”tt”来追溯函数调用过程:
-> tt "t_Lcd"
fe3c14f4 vxTaskEntry +68 : fe392a30 ()
fe392b48 initLcdComponent+2e8: fe392bdc ()
fe392bec initLcdComponent+38c: fe392bfc ()
fe39333c initLcdComponent+adc: lcdShowPassWord ()
fe398590 lcdShowPassWord+84 : saveModifiedSetting ()
fe3a3790 saveModifiedSetting+220: saveSettingValue (1)
fe1fd6d0 saveSettingValue+148: fe1fc428 (0, 5, ffffffff)
fe1fc888 getDeviceSettingValue+64c: fclose ()
fe1aab48 fclose +ec : free ()
fe1bb7d4 free +1c : memPartFree ()
fe1bb2dc memPartFree +148: taskSuspend ()
我们可以了解到函数的调用过程,vxTaskEntry()?->fe392a30()->fe392bdc ()->fe392bfc
()->lcdShowPassWord ()->saveModifiedSetting ()->saveSettingValue (1)->fe1fc428 (0, 5,
ffffffff)->fclose ()->free ()->memPartFree ()->taskSuspend ()。
其他相关信息:
第一栏是发生跳转(即函数调用)后的返回地址,稍后会作详细解释,
第二栏是离返回地址最近的symbol和偏移量,一般情况下会是发 起调用的那个函数的名称,除非该函数是内部函数,系统中没有symbol,
第三栏是被调用的函数。
再来查看一下t_Lcd任务的栈里的内容,从前面的任务信息里已经得知当前栈顶位置为fc8120b8,通过“d”命令显示该地址的内容。
-> d 0xfc8120b0
fc8120b0: fc81 25b8 fc81 25b8 fc81 20c8 fe1f 24b0 *..%...%... ...$.*
fc8120c0: fe50 8894 fdfc 6f30 fc81 20e8 fe1b b2dc *.P....o0.. .....*
fc8120d0: fdf2 6b08 0000 0100 0000 000c 0000 0000 *..k.............*
fc8120e0: 0000 0000 fdf1 ed80 fc81 20f8 fe1b b7d4 *.......... .....*
fc8120f0: fd9a 3538 fdf1 ed80 fc81 2108 fe1a ab48 *..58......!....H*
fc812100: fd9a 3538 fc81 2108 fc81 2238 fe1f c888 *..58..!..."8....*
fc812110: 0000 0000 0000 0005 ffff ffff 0000 0600 *................*
fc812120: 0000 000a fdf1 ed80 4230 312e 7874 6373 *........*
fc812130: 5f62 7566 2e69 6c32 0000 0000 0000 0000 *_2........*
这里我们可以看到一些熟悉的地址,注意看最后两列,在这里可以找到”tt”中显示的第一栏地址即函数调用的返回地址。两个返回地址之间是该函数的栈空间,用于保存栈指针、局部变量或者相关寄存器的值。要具体了解这些值是怎么来的,就要用到反汇编了。
反汇编通过objdump命令来实现,不同类型的cpu会有不同的可执行文件,例如:
objdumpppc -D vxworks >xx.s
反汇编的结果可能会很大,耐心等待吧。我们来看一下fclose()里调用free()的这一过程,在汇编代码里查找返回地址fe1aab48。
fe1aaa5c
……
fe1aab44: 48 01 0c 75 bl fe1bb7b8
fe1aab48: 38 00 00 00 li r0,0
bl是无条件跳转指令,free()执行完之后,应返回fe1aab48继续执行。
查找fe1bb7b8,看看free被调用时干了些什么?
fe1bb7b8
fe1bb7b8: 94 21 ff f0 stwu r1,-16(r1)
fe1bb7bc: 7c 08 02 a6 mflr r0
fe1bb7c0: 90 01 00 14 stw r0,20(r1)
fe1bb7c4: 7c 64 1b 78 mr r4,r3
fe1bb7c8: 3c 60 fe 51 lis r3,-431
fe1bb7cc: 38 63 88 94 addi r3,r3,-30572
fe1bb7d0: 4b ff f9 c5 bl fe1bb194
fe1bb7d4: 80 01 00 14 lwz r0,20(r1)
fe1bb7d8: 7c 08 03 a6 mtlr r0
fe1bb7dc: 38 21 00 10 addi r1,r1,16
fe1bb7e0: 4e 80 00 20 blr
虽然不同类型cpu的汇编指令不同,但还是可以大致猜出其中的含义。stwu指令将r1保存到地址(r1-16)位置,然后让将r1减去16保存到r1中,完成了保存并更新栈指针的过程;第2、3条语句将返回地址保存到r1+20的 位置;下面几条语句实际上是准备参数的过程,r3,r4一般用来保存函数的形参值,随后调用了memPartFree。从memPartFree返回后, 先从堆栈上读取返回地址,然后将栈顶下移16字节,即恢复到原来的位置,最后跳转到返回地址。
对着内存内容校验一下,fclose调用free后的返回地址为fe1aab48,按照上面的分析,这个地址会被free()函数保存在r1+20 的位置,因此r1+20=fc8120fc,r1=fc8120e8,而free中将r1减去了16,所以刚进入free()时,r1应该等于 fc8120f8,这个数值会被保存在fc8120e8处,事实正是如此。
这里栈内空间的利用有点交叉混杂,暂时没有弄的太明白,并且free()中没有用到过fc8120f0-fc8120f8空间的内存,推测可能是栈的大小至少为16字节所以留空了,里面的内容是历史遗留产物,是否如此,还有待进一步的研究。
以上是比较通用的分析过程,本来还涉及到结合c代码的分析,跟具体的例子结合太紧密,就不赘述了,有一点可以提一下,想追溯函数调用过程中某一参数 的运行值,可能会在调用者的栈中,也可能会在调用者的调用者的栈中,这个需要结合具体的汇编码来分析。因为函数的栈开辟出来是为了保存一些临时的乱七八糟 的东西,比如需要用到r38,就会把r38临时保存到栈上,返回时再恢复。而对本函数有用的变量,通常会被优化到寄存器中保存,除非寄存器不够用了,才会 用到栈空间。
发觉debug有时跟探案一样好玩。


发布评论