EAL: UIO_RESOURCE_LIST tailq is already registered PANIC in tailqinitfn_rte_uio_tailq(): Cannot initialize tailq: UIO_RESOURCE_LIST 程序退出



程序链接了DPDK库,启动就出错,打出如下信息:
EAL: UIO_RESOURCE_LIST tailq is already registered
PANIC in tailqinitfn_rte_uio_tailq():
Cannot initialize tailq: UIO_RESOURCE_LIST
分析发现,C语言定义了constructor属性的函数会先于main()执行,DPDK中定义了RTE_INIT()宏,用来声明一个如构造函数:



#define RTE_PRIO(prio) \
RTE_PRIORITY_ ## prio

/**
* Run function before main() with high priority.
*
* @param func
* Constructor function.
* @param prio
* Priority number must be above 100.
* Lowest number is the first to run.
*/
#ifndef RTE_INIT_PRIO /* Allow to override from EAL */
#define RTE_INIT_PRIO(func, prio) \
static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)
#endif

/**
* Run function before main() with low priority.
*
* The constructor will be run after prioritized constructors.
*
* @param func
* Constructor function.
*/
#define RTE_INIT(func) \
RTE_INIT_PRIO(func, LAST)


在tailq.h中定义了EAL_REGISTER_TAILQ()



/**
* Register a tail queue.
*
* Register a tail queue from shared memory.
* This function is mainly used by EAL_REGISTER_TAILQ macro which is used to
* register tailq from the different dpdk libraries. Since this macro is a
* constructor, the function has no access to dpdk shared memory, so the
* registered tailq can not be used before call to rte_eal_init() which calls
* rte_eal_tailqs_init().
*
* @param t
* The tailq element which contains the name of the tailq you want to
* create (/retrieve when in secondary process).
* @return
* 0 on success or -1 in case of an error.
*/
int rte_eal_tailq_register(struct rte_tailq_elem *t);

#define EAL_REGISTER_TAILQ(t) \
RTE_INIT(tailqinitfn_ ##t) \
{ \
if (rte_eal_tailq_register(&t) < 0) \
rte_panic("Cannot initialize tailq: %s\n", t.name); \
}


然后用定义了很多初始化构造函数,比如rte_ring.c中:



#define RTE_TAILQ_RING_NAME "RTE_RING"

static struct rte_tailq_elem rte_ring_tailq = {
.name = RTE_TAILQ_RING_NAME,
};
EAL_REGISTER_TAILQ(rte_ring_tailq)


出错原因是涉及到的constructor函数代码有多个实例,被重复调用。我遇到的实例是因为有重复静态链接:app链接了libxxx.a和librte_*.a, 并且libxxx.a也链接了librte_*.a,app里面就有两份librte_*.a的代码实例。

解决方法:把静态链接librte_*.a都改成动态链接librte_*.so

 

另:加入log,可发现在main()函数之前调用了很多EAL_REGISTER_TAILQ()函数:

EAL: rte_eal_tailq_register: name=RTE_RING

EAL: rte_eal_tailq_register: name=RTE_MEMPOOL

EAL: rte_eal_tailq_register: name=RTE_MBUF_DYNFIELD

EAL: rte_eal_tailq_register: name=RTE_MBUF_DYNFLAG

EAL: rte_eal_tailq_register: name=RTE_HASH

EAL: rte_eal_tailq_register: name=RTE_FBK_HASH

EAL: rte_eal_tailq_register: name=RTE_THASH

EAL: rte_eal_tailq_register: name=RTE_ACL

EAL: rte_eal_tailq_register: name=RTE_DIST_BURST

EAL: rte_eal_tailq_register: name=RTE_DISTRIBUTOR

EAL: rte_eal_tailq_register: name=RTE_EFD

EAL: rte_eal_tailq_register: name=RTE_KNI

EAL: rte_eal_tailq_register: name=RTE_LPM

EAL: rte_eal_tailq_register: name=RTE_LPM6

EAL: rte_eal_tailq_register: name=RTE_MEMBER

EAL: rte_eal_tailq_register: name=RTE_RIB

EAL: rte_eal_tailq_register: name=RTE_RIB6

EAL: rte_eal_tailq_register: name=RTE_REORDER

EAL: rte_eal_tailq_register: name=RTE_STACK

EAL: rte_eal_tailq_register: name=RTE_IPSEC_SAD

EAL: rte_eal_tailq_register: name=RTE_FIB

EAL: rte_eal_tailq_register: name=RTE_FIB6