DPDK — 擴展私有函數庫

目錄

DPDK 擴展第三方函數庫

在開發 DPDK App 的時候難免會需要在 DPDK 中擴展自己的庫或者直接引入第三方函數庫。

  • 本文版本:DPDK 18.08
  • 官方參考網頁:https://dpdk-docs.readthedocs.io/en/latest/prog_guide/extend_dpdk.html

擴展一個新的 libfoo 庫

添加擴展庫的啓用配置

for f in config/\*; do \
    echo CONFIG_RTE_LIBFOO=y >> $f; done

上述腳本的作用是爲所有的 目標環境(Target Env) 中添加擴展庫的配置項,表示編譯該擴展庫。

$ ll  ${RTE_SDK}/config/

以最常見的 x86_64-native-linuxapp-gcc 爲例,文件爲 ${RTE_SDK}/config/defconfig_x86_64-native-linuxapp-gcc:

#include "common_linuxapp"

CONFIG_RTE_MACHINE="native"

CONFIG_RTE_ARCH="x86_64"
CONFIG_RTE_ARCH_X86_64=y
CONFIG_RTE_ARCH_X86=y
CONFIG_RTE_ARCH_64=y

CONFIG_RTE_TOOLCHAIN="gcc"
CONFIG_RTE_TOOLCHAIN_GCC=y

# Extended libfoo library.
CONFIG_RTE_LIBFOO=y

實現擴展庫

創建源碼目錄:

$ mkdir ${RTE_SDK}/lib/libfoo
$ touch ${RTE_SDK}/lib/libfoo/foo.c
$ touch ${RTE_SDK}/lib/libfoo/foo.h

我們要擴展的是 DPDK 庫,所以庫目錄自然也創建在 ${RTE_SDK}/lib 路徑下。

源文件 foo.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "foo.h"


void foo(void)
{
    printf("libfoo test appliation.\n");
    fprintf(stdout, "%s %d\n", __func__, __LINE__);
}·

頭文件 foo.h:

#ifndef _RTE_FOO_H_
#define _RTE_FOO_H_

extern void foo(void);

#endif

添加擴展庫的 Makefile

首先我們需要添加擴展庫的 Makefile,可以從 mempool Makefile 獲取模板:

$ cp ${RTE_SDK}/lib/librte_mempool/Makefile ${RTE_SDK}/lib/libfoo/

替換 ${RTE_SDK}/lib/libfoo/Makefile 的內容:

  • 靜態庫文件:librte_mempool.a -> libfoo.a
  • 原文件名:rte_mempool.c -> foo.c
  • 頭文件:rte_mempool.h -> foo.h
  • 中間編譯的符號映射文件:rte_mempool_version.map -> foo_version.map
  • 擴展庫配置項名稱:CONFIG_RTE_LIBRTE_MEMPOOL -> CONFIG_RTE_LIBFOO
include $(RTE_SDK)/mk/rte.vars.mk

# library name
LIB = libfoo.a

CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
CFLAGS += -DALLOW_EXPERIMENTAL_API
LDLIBS += -lrte_eal -lrte_ring

EXPORT_MAP := foo_version.map

LIBABIVER := 5

# memseg walk is not yet part of stable API
CFLAGS += -DALLOW_EXPERIMENTAL_API

# all source are stored in SRCS-y
SRCS-$(CONFIG_RTE_LIBFOO) += foo.c

# install includes
SYMLINK-$(CONFIG_RTE_LIBFOO)-include := foo.h

include $(RTE_SDK)/mk/rte.lib.mk

然後,更新總庫的 Makefile:${RTE_SDK}/lib/Makefile

...
DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool
DIRS-$(CONFIG_RTE_LIBFOO) += libfoo

最後,還需要更新 ${RTE_SDK}/mk/rte.app.mk 文件,添加 -lfoo 選項到 LDLIBS 變量中:

...
_LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL)        += -lrte_mempool
_LDLIBS-$(CONFIG_RTE_LIBFOO)                += -lfoo

如此的,在編譯 DPDK 的時候就會連帶的編譯 libfoo 擴展庫了。

重新編譯安裝 DPDK 的目標環境

rm -rf ${RTE_SDK}/x86_64-native-linuxapp-gcc
cd ${RTE_SDK}
make config T=x86_64-native-linuxapp-gcc
make
make install T=x86_64-native-linuxapp-gcc

如果擴展庫 libfoo 安裝成功,DPDK 會自動創建 foo.h 的鏈接文件和創建 libfoo.a 靜態鏈接庫文件:

$ ll ${RTE_SDK}/x86_64-native-linuxapp-gcc/include/ | grep foo
lrwxrwxrwx 1 root root    22 6月  19 00:03 foo.h -> ../../lib/libfoo/foo.h

$ ll ${RTE_SDK}/x86_64-native-linuxapp-gcc/lib/ | grep foo
-rw-r--r-- 1 root root   1964 6月  19 00:03 libfoo.a

在自己的 DPDK App 中使用擴展庫

創建 DPDK App 項目:

$ ~/workspace/myapp/

源文件 main.c:

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/queue.h>

#include <rte_memory.h>
#include <rte_memzone.h>
#include <rte_launch.h>
#include <rte_tailq.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_debug.h>

#include <foo.h>


int main(void)
{
    foo();
    return 0;
}

獲取 App 的 Makefile 模板:

$ cp ${RTE_SDK}/examples/helloworld/Makefile  ~/workspace/myapp/Makefile

替換成:

# binary name
APP = myapp

# all source are stored in SRCS-y
SRCS-y := main.c

# Build using pkg-config variables if possible
$(shell pkg-config --exists libdpdk)
ifeq ($(.SHELLSTATUS),0)

all: shared
.PHONY: shared static
shared: build/$(APP)-shared
    ln -sf $(APP)-shared build/$(APP)
static: build/$(APP)-static
    ln -sf $(APP)-static build/$(APP)

PC_FILE := $(shell pkg-config --path libdpdk)
CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)

build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
    $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)

build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
    $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)

build:
    @mkdir -p $@

.PHONY: clean
clean:
    rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
    rmdir --ignore-fail-on-non-empty build

else

ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif

# Default target, can be overridden by command line or environment
RTE_TARGET ?= x86_64-native-linuxapp-gcc

include $(RTE_SDK)/mk/rte.vars.mk

CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)

include $(RTE_SDK)/mk/rte.extapp.mk

endif

編譯 App:

$ make -C ~/workspace/myapp/
make: 進入目錄“/root/workspace/myapp”
  CC main.o
  LD myapp
  INSTALL-APP myapp
  INSTALL-MAP myapp.map

$ # ll ~/workspace/myapp/
總用量 8
drwxr-xr-x 3 root root  188 6月  19 00:13 build
-rw-r--r-- 1 root root  355 6月  19 00:13 main.c
-rw-r--r-- 1 root root 1381 6月  19 00:11 Makefile

$ ll ~/workspace/myapp/build/
總用量 10680
drwxr-xr-x 2 root root      36 6月  19 00:13 app
-rw-r--r-- 1 root root       0 6月  19 00:13 _install
-rw-r--r-- 1 root root    1448 6月  19 00:13 main.o
-rwxr-xr-x 1 root root 7174064 6月  19 00:13 myapp
-rw-r--r-- 1 root root 3754908 6月  19 00:13 myapp.map
-rw-r--r-- 1 root root       0 6月  19 00:13 _postbuild
-rw-r--r-- 1 root root       0 6月  19 00:13 _postinstall
-rw-r--r-- 1 root root       0 6月  19 00:13 _preinstall

執行:

$ ./myapp/build/myapp
libfoo test appliation.
foo 11
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章