声明:此文档只做学习交流使用,请勿用作其他商业用途
author:朝阳_tony转载请注明出处:http://blog.csdn.net/linzhaolover
此文请结合intel dpdk源码去阅读,源码可以去http://dpdk.org/dev 网页中下载;更多官方文档请访问http://dpdk.org
本文章基于intel dpdk 的源码1.3.1 版本进行讲解;
参考文档 “gcc警告选项” http://blog.csdn.net/onlyou930/article/details/6553800
intel dpdk 的makefile 写的很好,该好好学习他的这种架构,但在调试程序时候发现,它的编译选项优化级别很高;怎样去修改intel dpdk中的编译选项,达到自己一个一个满意的程度;其大部分makefile规则都定义在dpdk/mk目录下;最后再说一下怎样用gdb工具调试dpdk;
# ls mk/
arch rte.app.mk rte.extshared.mk rte.hostlib.mk rte.obj.mk rte.sdkdoc.mk rte.sdktestall.mk rte.vars.mk
exec-env rte.extapp.mk rte.extvars.mk rte.install.mk rte.sdkbuild.mk rte.sdkgcov.mk rte.sdktest.mk target
internal rte.extlib.mk rte.gnuconfigure.mk rte.lib.mk rte.sdkconfig.mk rte.sdkinstall.mk rte.shared.mk toolchain
machine rte.extobj.mk rte.hostapp.mk rte.module.mk rte.sdkdepdirs.mk rte.sdkroot.mk rte.subdir.mk
说一下常见的几个现象及解决方法;
为了测试程序,肯定会有一些变量临时注释掉,或者有些变量定义了,但没有赋值,有些函数定义了,但不去调用;可是dpdk在编译的时候,只要有错误警告就会编译退出;
解决办法:
vim mk/toolchain/gcc/rte.vars.mk
打开mk/toolchain/gcc/rte.vars.mk文件,其中有这几行
WERROR_FLAGS := -W -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
WERROR_FLAGS += -Wmissing-declarations -Wold-style-definition -Wpointer-arith
WERROR_FLAGS += -Wcast-align -Wnested-externs -Wcast-qual
WERROR_FLAGS += -Wformat-nonliteral -Wformat-security
第一行中的-Werror 选项就是指在gcc编译的时候,有任何错误就停止编译,直接退出,将这个选项去的就可以只报警告,除非真有错误退出了;
以dpdk/examples/l2fwd/Makefile文件为例
# binary name
APP = l2fwd
# all source are stored in SRCS-y
SRCS-y := main.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
l2fwd 是指编译出来的可执行程序名称;
main.c 是l2fwd程序的源码;
-O3 是只gcc的编译优化选项,如果不想优化基本这么高,可以将其改为 -O0、-O1 、 -O2 等等 ;
CFLAGS += $(WERROR_FLAGS) 如果把这一行去的,就是去掉所有的编译警告选项,易可以达到在1部分写的去除编译警告退出的目的,但这就有点过了,有点警告才能知道自己的程序哪有问题;
有时候我们想用gdb调试我们的程序,应该怎样添加编译选项呢
export RTE_SDK=`pwd`
export RTE_TARGET=x86_64-default-linuxapp-gcc
export EXTRA_CFLAGS="-O0 -g"
在dpdk目录,设置一下上面的环境变量,其实主要是为了设置makefile用到的编译选项EXTRA_CFLAGS 将其优化级别设置为 -O0 , 还有gdb的调试选项 -g;
make -C x86_64-default-linuxapp-gcc/
make -C examples/l2fwd/
我测试的是l2fwd这个实例程序,其他实例程序编译大同小异;
执行 gdb examples/l2fwd/build/l2fwd 运行测试程序;
# gdb examples/l2fwd/build/l2fwd
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-50.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /home/linzhao/repo/dpdk_project/dpdk/examples/l2fwd/build/l2fwd...done.
(gdb)
你可能回想,在执行程序的时候不是要输入程序的所需要的参数吗,不用急,在运行的时候在输入参数就行;
在gdb中执行 l 这个命令,就是list 的第一字母执行显示,看一下程序;在哪儿打断点比较好;
(gdb) l
593
594 /* init EAL */
595 ret = rte_eal_init(argc, argv);
596 if (ret < 0)
597 rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
598 argc -= ret;
599 argv += ret;
600
601 /* parse application arguments (after the EAL ones) */
602 ret = l2fwd_parse_args(argc, argv);
用b ,break的第一字母打断点;
(gdb) b 595
Breakpoint 1 at 0x40f420: file /home/linzhao/repo/dpdk_project/dpdk/examples/l2fwd/main.c, line 595.
(gdb) b 602
Breakpoint 2 at 0x40f461: file /home/linzhao/repo/dpdk_project/dpdk/examples/l2fwd/main.c, line 602.
注意我传入的参数, -c 1f 是指定5个core, -n4 是四通道, -p 3 是用两个端口;
(gdb) r -c 1f -n 4 -- -p 3
Starting program: /home/linzhao/repo/dpdk_project/dpdk/examples/l2fwd/build/l2fwd -c 1f -n 4 -- -p 3
[Thread debugging using libthread_db enabled]
Breakpoint 1, main (argc=8, argv=0x7fffffffe248) at /home/linzhao/repo/dpdk_project/dpdk/examples/l2fwd/main.c:595
595 ret = rte_eal_init(argc, argv);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.47.el6.x86_64
现在程序运行到了我第一个断点595行处,
然后执行单步运行命令s ,也是step的缩写;看是否能进入rte_eal_init程序运行;
(gdb) s
rte_eal_init (argc=8, argv=0x7fffffffe248) at /home/linzhao/repo/dpdk_project/dpdk/lib/librte_eal/linuxapp/eal/eal.c:809
809 struct shared_driver *solib = NULL;
(gdb) s
811 if (!rte_atomic32_test_and_set(&run_once))
(gdb) s
rte_atomic32_test_and_set (v=0x6c0c40) at /home/linzhao/repo/dpdk_project/dpdk/x86_64-default-linuxapp-gcc/include/arch/rte_atomic.h:641
641 return rte_atomic32_cmpset((volatile uint32_t *)&v->cnt, 0, 1);
从跟踪的信息看到,我们已经进入了dpdk/lib/librte_eal/linuxapp/eal/eal.c文件中,进行代码调试工作;
技术水平有待提高,如果文章有错误的地方希望读者指正,相互交流,互相学习;O(∩_∩)O~