
英创应用程序助手AppHelper使用说明.pdf
13页成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 1 / 13 英创应用程序助手 AppHelper 使用说明 为保证系统稳定运行,系统 CPU 应避免长时间满负荷运作,应用程序 CPU 占用不宜过高客户需要在调试阶段监测应用程序各个进程线程占用情况,对占用过高的进程线程进行优化因 CE 自身不带进程线程系统占用查看工具,我们增加了 AppHelper 助手工具方便客户使用 在之前的技术文章《CE 应用程序助手简介》中简单介绍过英创 AppHelper 应用程序助手,本文将详细介绍 AppHelper 的使用方法 AppHelper 查看方法 客户在自制底板上只要引出了网络,USBOTG,DEBUG 调试串口,或板子其它串口任意之一便可以查看 AppHelper 信息 网络方式 通过 telnet 登录上板子,运行命令 sysinfo,即可获得 AppHelper 打印的进程线程信息 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 2 / 13 telnet 模式打印示例图 USBOTG 方式 使用 AHC 工具(使用方法见本文下一节)配置 AppHelper 输出为 COM1。
连接上板子 USBOTG口,板子将以虚拟串口形式被 PC 识别使用任意串口工具向该串口输出任意三个字符(任意波特率),即可获得 AppHelper 打印的进程线程信息 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 3 / 13 USBOTG,DEBUG 及其它串口打印示例图 DEBUG 调试串口方式 使用 AHC 工具(使用方法见本文下一节)配置 AppHelper 输出为 DEBUG连接板子的 DEBUG串口,PC 端使用任意串口工具,设置波特率 115200,向 DEBUG 口输出任意三个字符,即可获得AppHelper 打印的进程线程信息 串口方式 将底板上引出,且客户应用程序未使用的串口连接上 PC使用 AHC 工具(使用方法见本文下一节)配置好串口号及波特率PC 端使用任意串口工具,用设定的波特率向该串口输出任意三个字符,即可获得 AppHelper 打印的进程线程信息 AHC 工具使用介绍 AHC 工具即 AppHelper Config 工具,用于设置 AppHelper 打印信息的输出位置有两种办法进行设置 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 4 / 13 控制面板方式 在板子控制面板中运行 AHC 工具。
选择好输出信息的串口及波特率(其中 COM1 为 USBOTG),点击 OK 键保存配置,板子重启后配置生效 telnet 方式 通过 telnet 登录上板子,执行命令 AHC port [baud] 参数 port:串口号,值为 0-6,0 表示 DEBUG 串口,1 表示 USBOTG 转虚拟串口,2-6 分别表示板子的 COM2-COM6 参数 baud:波特率,可选参数,如果不填表示保持原波特率,支持 1200,2400,4800,9600,19200,38400,57600,115200当 port 为 0 时,baud 固定为 115200,当 port 为 1 时,baud 值不生效 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 5 / 13 命令执行后,DEBUG 口可以看到打印提示信息 打印格式说明 打印结果为数行,其中每行的格式均为:类型 ID 号 占用情况 名称 以下图一次打印的部分截图为例: 类型 PID 表示为 process 进程TID 表示为上面进程下的 thread 线程 ID 号 即进程 ID 值或线程 ID 值 占用情况 显示格式为 K n% U m% total% 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 6 / 13 n 值为该进程或线程在 Kernel 系统层的占用 m 值为该进程或线程在 User 用户层的占用 total 值为总占用,它应当等于 n+m 的和 进程下各个线程 total 占用和应当等于进程的 total 占用 名称 进程名即 EXE 的名称,线程默认没有名称,下一节会介绍如何给线程命名,从而能在AppHelper 中显示出来。
进程及线程监视说明 AppHelper 会打印系统下所有的进程的 CPU 占用信息 只有在\NandFlash 目录下的 exe 生成的进程会额外打印出它下面所有线程的 CPU 占用信息 默认情况下,生成的线程只有 ID 号,没有名称,如果线程较多会不便于查看我们可以通过简单代码给线程命名 以光盘里的串口例程 SPT_HEX 为例: 添加一个结构体的定义 typedef struct _THREAD_INDEX { DWORDdwSize; DWORDdwThreadID; TCHARszThreadName[32]; _THREAD_INDEX*pNext; 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 7 / 13 }THREAD_INDEX; 在创建线程后给线程命名 这里把串口接收线程命名为“CommRecvTread“ hRecvThread = CreateThread(0, 0, CommRecvTread, this, 0, HANDLE hHLP; DWORD dwLen; hHLP = CreateFile(L“HLP1:“, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); THREAD_INDEXthreadIndex; wsprintf(threadIndex.szThreadName, L“CommRecvTread“); threadIndex.dwThreadID = m_dwTID; threadIndex.dwSize = sizeof(THREAD_INDEX); WriteFile(hHLP, CloseHandle(hHLP); 在结束线程后取消命名 线程结束后应当手动将命名取消掉,避免不必要的显示错误,设置线程名为空,即可取消原命名。
HANDLE hHLP; DWORD dwLen; hHLP = CreateFile(L“HLP1:“, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); THREAD_INDEXthreadIndex; wsprintf(threadIndex.szThreadName, L““); threadIndex.dwThreadID = m_dwTID; threadIndex.dwSize = sizeof(THREAD_INDEX); 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 8 / 13 WriteFile(hHLP, CloseHandle(hHLP); 命名线程后再使用 AppHelper 查看,启动接收线程后,就可以看到 CommRecvTread 这个线程,另外个没有命名的线程为 SerialPort 程序的主线程 计算原理及误差说明 CPU 占用时间是通过计算一段时间内(AppHelper 设置为 2000 毫秒)CPU 空闲 tick 值与这段时间里 CPU 运算周期 tick 值得出。
CPU 空闲 tick 值 = CPU 空闲 tick 计数 t2 – CPU 空闲 tick 计数 t1 CPU 总周期 tick 值 = CPU 总周期 tick 计数 t2 – CPU 总周期 tick 计数 t1 CPU 占用 = 1 – (CPU 空闲 tick 值/CPU 总周期 tick 值)× 100% 进程或线程的 CPU 占用,是通过计算一段时间 CPU 运算周期 tick 值,和这段周期里 Kernel 或User 运行线程或进程的 tick 值,通过相除得到 进程/线程 Kernel 占用 = (进程/线程 Kernel 运行 tick 值/CPU 总周期 tick 值)× 100% 进程/线程 User 占用 = (进程/线程 User 运行 tick 值/CPU 总周期 tick 值)× 100% 进程/线程 CPU 占用 = 进程/线程 Kernel 占用 + 进程/线程 User 占用 打印结果可能会有少量误差,可能由于以下原因: 1、实验值计算到个位,小数部分四舍五入,所以可能产生细微的误差 2、理想中的测量情况如下图 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 9 / 13 但是实际情况由于 AppHelper 本身也会产生系统消耗,所以测量情况为下图 在Δt 值不为 0 的情况下,如果在Δt 期间各个 tick 值产生较大跳动时,测试结果可能产生误差。
成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 10 / 13 3、各个进程或线程的运行 tick 值并非完全实时变化,而是在进程或线程完成一个时间片挂起后才加上,所以查询函数获得值不一定非常精确 测试程序及说明 test_prc_thd 是一个简单的程序,用来测试 AppHelper 的进程线程监视功能 “添加线程”按钮按下会创建一个新的线程参数中传入线程编号,线程 ID 等信息 void Ctest_prc_thdDlg::OnBnClickedButton1() { DWORD dwTID; HANDLE hTestThread; m_threadParam[m_dwCnt].dwCnt = m_dwCnt; m_threadParam[m_dwCnt].dwLv = m_dwCnt; m_threadParam[m_dwCnt].bThreadStop = FALSE; hTestThread = CreateThread(0, 0, TestTread, m_threadParam[m_dwCnt].dwThreadID = dwTID; ResumeThread(hTestThread); CloseHandle(hTestThread); } 线程主函数里根据编号给线程自身命名,并且根据各自传入的参数执行负载率不等的计算。
这里计算采用简单的循环计数,循环计算次数越多,线程 CPU 占用越多 线程结束后,取消自身的命名 成都英创信息技术有限公司 英创应用程序助手 AppHelper 使用说明 11 / 13 DWORD Ctest_prc_thdDlg::TestTread(LPVOID lparam) { THREAD_PARAM *pThreadParam = (THREAD_PARAM*)lparam; DWORDdwLen; THREAD_INDEXthreadIndex; HANDLE hHLP; volatile int n; hHLP = CreateFile(L“HLP1:“, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); wsprintf(threadIndex.szThreadName, L“thread%d“, pThreadParam->dwCnt); threadIndex.dwThreadID = pThreadParam->dwThreadID; threadIndex.dwSize = sizeof(THREAD_INDEX); WriteFile(hHLP, CloseHandle(hHLP); HANDLEhFile; WCHARwsFileName[64]; inti; while(!pThreadParam->bThreadStop) { fo。












