gnuradio调试方法

How to debug GNU Radio applications

Once you've started creating GNU Radio applications, you will probably stumble upon some errors sooner or later. Here is some advice on how to tackle those problems.

Simple debugging otions

Most often, it is enough to inspect the data flowing out of blocks during run-time to get an idea where an error might occur. This is usually the case if a flow graph runs without
crashing, but the final result is not correct.

The following options are easy to implement and will be useful for GNU Radio users of any skill level.

Use the QA codes

This is the most obvious and simple tool anyone should use. For every block you write, add QA code as well. In fact, write it first. Test as many options as you can think
of which might cause trouble. Individual blocks should always pass tests.

If your blocks are failing, here's some suggestions on how to hunt down bugs:

  • Use ctest -V instead of make test to make the testing output more verbose. If you only want to run a specific test, use the -Rswitch to select tests that match a certain regular expression (e.g. ctest -V -R foobar_ff will
    only run tests that matchfoobar_ff, and will show all output)
  • If necessary, add additional print statements in the code (or even in your block) to show intermediary states until the tests pass
  • As a last resort, attach debuggers such as gdb or pdb (see the section on Expert Debugging Tools below)

Using GRC and the graphical sinks

This is a very simple solution. If possible, try and develop your applications with the GNU
Radio companion
. This tool has graphical sinks which you can simply attach to your block. Among the WX GUI Widgets and the QT GUI Widgets you can find FFT plots, Oscilloscopes and number sinks (which will simply display the value of the
data). Depending on what kind of data you have, choose an approprate sink and attach it to your block. You can disable the graphical sink later if you don't want to delete it from the flow graph.

Dumping data into files between blocks

For a more detailed analysis of your data, you might want to perform an off-line analysis using other tools than GNU Radio, e.g. Octave, SciPy (with Matplotlib) or Matlab. The easiest
way is to connect a file sink to the block you suspect is making trouble, run the flow graph and then load the file with the tool of your choice. Read the
guide to using Octave and Matlab with GNU Radio
.

Expert debugging tools

There's some tools you may use to inspect your code on a deeper level:

  • gdb - The GNU debugger (assuming you're using gcc). This allows you to step through your code, but it might not be useful for multithreaded debugging.

If your block isn't working, and you can't sort it out through python test cases or a few printfs in the code, you may want to use gdb to debug it. This makes sense if the blocks
you're using are written in C++ (even if called from Python).

Try this: In your python test code, after the relevant imports, print out the process id and wait for a keystroke. In another window run gdb and tell it to attach to the python
process with the given process id. At this point you can set breakpoints or whatever in your code. Go back to the python window and hit Enter so it'll continue.

There's also:

  • oprofile - Profiling tool
  • kcachegrind / valgrind - Another profiling tool

Tutorial: Using gdb with Pythonic GR applications

Note that this tutorial assumes some familiarity with gdb.

To try this at home, make and install the gr-howto-write-a-block module that comes with GNU Radio. Make sure that you can access the module from Python by calling import howto.

This is the script we want to debug:

""" Testing GDB, yay """ 

import os
from gnuradio import gr
import howto

class SquareThat(gr.top_block):
    def __init__(self):
        gr.top_block.__init__(self, name="square_that")
        self.src = gr.vector_source_f((1, 2, 3, 4, )*5)
        self.sqr = howto.square2_ff()
        self.sink = gr.vector_sink_f()
        self.connect(self.src, self.sqr, self.sink)

def main():
    """ go, go, go """
    top_block = SquareThat()
    top_block.run()

if __name__ == "__main__":
    print 'Blocked waiting for GDB attach (pid = %d)' % (os.getpid(),)
    raw_input ('Press Enter to continue: ')
    main()

First of all, it helps if you compiled the howto module with debug symbols. CMake will do that for you if you invoke it with

$ cmake .. -DCMAKE_BUILD_TYPE=Debug

Make sure to re-make and re-install if you recompiled this way.

Now, all you have to do is start the script. Let's assume it's saved as test_gdb.py:

$ python test_gdb.py
Blocked waiting for GDB attach (pid = 27049)
Press Enter to continue:

As you can see, the script is stalled, waiting for the user to hit enter. We will use this pause to call gdb in a different terminal window:

$ gdb -p 27049

Make sure to use the same PID as the Python script has.

Ubuntu users: The kernel will not simply let you poke around in processes, even if they have the same UID as you do, so the command above will give you an error
message. Either call sudo gdb, or deactivate the ptrace blocking by calling echo 0 > /proc/sys/kernel/yama/ptrace_scope as root. To permanently allow this, set the corresponding value to 0 in /etc/sysctl.d/10-ptrace.conf.
For more information, see the Ubuntu page on kernel
hardening
 .

Once gdb has started, and you've successfully reached the gdb prompt, press enter in the terminal window running the Python script. gdb is now in control of your process, so it
won't continue before you tell it to.

Now, at the moment, gdb is stuck somewhere in the middle of nowhere, in some weird libs you've probably never heard of. To get straight to the heart of your block, set a breakpoint
and wait until it's reached. Use the gdb tab-completion to navigate through the namespaces. You could for example set it to break in the work() function of the square2_ff block:

(gdb) break gr::howto::square2_ff_impl::work(int, std::vector<void const*, std::allocator<void const*> >&, std::vector<void*, std::allocator<void*> >&)
Breakpoint 1 at 0x7f4938ab2303: file [...]/gr-howto-write-a-block/lib/square2_ff_impl.cc, line 86.

Note that square2_ff::work() is virtual, so remember the impl.

If you continue now, it will stop right there:

(gdb) cont
Continuing.
[New Thread 0x7f4938aae700 (LWP 27863)]
[New Thread 0x7f49382ad700 (LWP 27864)]
[Thread 0x7f4938aae700 (LWP 27863) exited]
[New Thread 0x7f4937aac700 (LWP 27865)]
[Switching to Thread 0x7f49382ad700 (LWP 27864)]

Breakpoint 1, gr::howto::square2_ff_impl::work (this=0x273ac30, noutput_items=20, input_items=...,
    output_items=...) at /home/braun/tmp/gr-howto-write-a-block/lib/square2_ff_impl.cc:86
86            const float *in = (const float*)input_items[0];

Recognize that last line? It's the first line of square2_ff_impl::work().
Now you can step merrily through your functions as you wish.

Note that GNU Radio is heavily multi-threaded, which can make usage of gdb quite complicated. The gdb command info threads will give you a list of active threads.

Directly debugging the QA codes

If your block is failing during QA, you don't have to install the module. However, ctest buffers the output, so the line showing the PID won't work. Instead, just put in the line
that waits for the input:

if __name__ == '__main__':
    raw_input ('Press Enter to continue: ')
    gr_unittest.run(qa_howto, "qa_howto.xml")

And then figure out the PID using some system tool, e.g.:

$ ps ux | grep qa_howto.py
XXXXX    28518  0.1  0.2 307476 23660 pts/9    tNl+ 13:45   0:00 /usr/bin/python [...]/gr-howto-write-a-block/python/qa_howto.py

Then you can use gdb -p 28518 as before.

The faster alternative: Debugging crashed programs (Post-Mortem)

An alternative method uses GDB to read a core dump file that is produced when a program crashes. Running a program in GDB can slow things down and potentially hide the error that
would occur under normal operation. This method avoids that problem.

First you must enable core dumps (which are mostly disabled by default these days). The ulimit -a command queries the current limits:

$ ulimit -a
core file size          (blocks, -c) 0

We use the ulimit command to turn off the limit:

$ ulimit -c unlimited
$ ulimit -a
core file size          (blocks, -c) unlimited

Now run the app, and wait for the crash. It should generate a file called core or core.PID in the current directory. There are a few other obscure
reasons that could also prevent the core file from appearing at this point (already a file with the same name but not owned by the user; user does not own the directory; executable is setuid, etc).

For this example assume the core file is named core.12345. Now do

gdb /usr/bin/python core.12345

This should load the core dump into GDB. Now you can do

i stack

to display the call trace.

http://gnuradio.org/redmine/projects/gnuradio/wiki/TutorialsDebugging

时间: 2024-10-03 11:47:25

gnuradio调试方法的相关文章

php程序调试方法总结

  相信很多朋友们都有调试程序的经历,然而很多时候调试程序是痛苦而又漫长的过程;它不仅需要细心,更需要耐心,切忌心浮气躁.但是当找出问题并顺利解决它时,又会给人无比激动的喜悦.这里总结一下笔者在程序调试中的使用的原则,工具,以及方法.这里需要说明的是,某些原则性的东西,各种语言都是差不多的,而涉及到具体的工具和某些具体的调试方法,这里只涉及web开发方面的内容. 总体原则: 1.找出问题原因: 程序需要调试,是因为程序有问题.而调试的第一目标是找到原因.常见调试方法, 排除法: 当我们面对整个复

VC++调试方法和技巧

便于调试的代码风格: 不用全局变量 所有变量都要初始化,成员变量在构造函数中初始化 尽量使用const 详尽的注释 VC++编译选项: 总是使用/W4警告级别 在调试版本里总是使用/GZ编译选项,用来发现在Release版本中才有的错误 没有警告的编译:保证在编译后没有任何警告,但是在消除警告前要进行仔细检查 调试方法: 1.使用 Assert(原则:尽量简单) assert只在debug下生效,release下不会被编译. 例子: char* strcpy(char* dest,char* s

思科路由器全局调试方法概述

使用思科路由器的用户非常多,关于思科路由器的全局调试今天在这里我为大家介绍一下,希望对大家有用. 在进行思科路由器配置时,全局和接口命令的界限是十分明显的.在这种情况下,我们使用全局来标识那些不能用于接口调试或者特定的传输介质类型和协议调试的命令. 在2500系列思科路由器中,就可以使用调试命令分析Cisco发现协议(Cisco Discovery Protocol,CDP).我们通过telnet远程登录到思科路由器.在缺省方式下,调试命令的输出被发送到控制台,如果处于telnet会话中,我们可

新扬天、昭阳、VBKEM机型安装系统BIOS的调试方法

  故障现象: 新扬天.昭阳.VBKEM机型安装系统BIOS的调试方法以及安装系统时常见的问题 解决方案: 提示:以下操作可能会导致无法正常进入系统,建议您备份个人数据后在专业人士指导下操作. 1. 进入"BIOS",选择最后"Restart"的选项,先选择"OS Optimized Defaults"的选项敲"enter键(回车键)"改成"Disabled"的模式.然后选择"Load Defau

新消费YSZGN机型安装系统Bios的调试方法

  故障现象: 新消费YSZGN机型安装系统Bios的调试方法以及安装系统时常见的问题. 解决方案: 提示:以下操作可能会导致无法正常进入系统,建议您备份个人数据后在专业人士指导下操作. 1. 进入"bios",选择最后"Exit"的选项,先选择"OSOptimized Defaults"的选项敲"enter键(回车键)"改成"other os"的模式.然后选择"Load Default Sett

VxWorks操作系统shell命令与调试方法总结

VxWorks下的调试手段 主要介绍在Tornado集成开发环境下的调试方法和利用支撑定位问题的步骤.思路. 1         Tornado的调试工具 嵌入式实时操作系统VxWorks和集成开发环境Tornado的组成结构如下图1.分为主机和目标机系统. 图1 集成开发环境结构图 在Tornado下调试相关操作在Debug菜单下包括 图2 Debug菜单 简单解释各菜单项的功能 1.1        WindShell 1.1.1         简介 Vxworks的Shell分为两种ho

cs客户端+oracle数据库调试方法有哪些

问题描述 cs客户端+oracle数据库调试方法有哪些 之前都是一直做服务端的,我知道服务端调试的时候可以是debug,trace,还有浏览器的F12,SqlServer数据库里面也可以查看左右跟数据库有关的操作语句,对客户端跟oracle 数据库不怎么熟悉,请教一下,cs除了debug还能怎么调试程序,oracle,plsql要怎么样才能查看所有数据库的进进出出的sql. 解决方案 有没有大神出来打打酱油什么的啊

VC调试方法大全

一.调试基础 调试快捷键 F5:  开始调试 Shift+F5: 停止调试 F10:   调试到下一句,这里是单步跟踪  F11:   调试到下一句,跟进函数内部 Shift+F11:  从当前函数中跳出 Ctrl+F10:  调试到光标所在位置 F9:       设置(取消)断点 Alt+F9:    高级断点设置 跟踪调试 1. 尽量使用快捷键时行调试 2. 观察调试信息 3. 高级中断设置 异常调试 重试->取消->调试 函数堆栈,用variables或者call stack 窗口 R

Linux环境中堆栈和堆相关内存损坏的基本原理和调试方法介绍

本文讲的是Linux环境中堆栈和堆相关内存损坏的基本原理和调试方法介绍, 前言 建议阅读本文之前,你对ARM组件的有个基本了解,本文会先为你介绍32位Linux环境中进程的内存布局,然后再介绍堆栈和堆相关内存损坏的基本原理以及调试方法. 本文中使用的示例是在ARMv6 32位处理器上编译的,如果你无法访问ARM设备,可以点击这里https://azeria-labs.com/emulate-raspberry-pi-with-qemu/创建自己的实验环境并在虚拟机中模拟Raspberry Pi发