天天看點

SPDK/DPDK靜态連結庫踩坑

作者:後端開發進階

最近幾天,嘗試內建 SPDK 到我們的分布式系統裡。為了避免對 SPDK 進行較大的改動,決定使用靜态連結庫,然後利用 SPDK 的 API 寫 target。

編譯 SPDK ,寫一個簡單的 target 例子都很順利。但是當運作的時候,reactor 初始化配置設定mempool 一直錯誤。這個錯誤非常奇怪。第一時間懷疑 hugepage 空間不足,但是仔細看了一下,肯定是夠的。

與此同時,發現同樣的 DPDK 配置,SPDK 自帶的 app 都可以初始化成功。從日志看一模一樣,除了最後,自己寫的初始化 mempool 失敗,自帶的可以成功。百思不得其解。

終于在 SPDK 的 issue 裡看到了一個同樣的錯誤:

lib/event/reactor.c: 685:spdk_reactors_init: ERROR: spdk_event_mempool creation failed           

根據回報看,應該是 __attribute__ ((constructor)) 的問題。

經過在初始化路徑上加上日志,發現就是這個問題。但是,為什麼會這樣呢?

這個擴充屬性,不就是 gcc 預設就打開了麼?

經過試驗發現,原來,問題出在靜态庫上。

$ cat foo.c 
#include <stdio.h>

__attribute__((constructor)) void foo()
{
    printf("foo called\n");
}

#include<stdio.h>
__attribute__((constructor)) void before_main() {
   printf("Before main\n");
}
__attribute__((destructor)) void after_main() {
   printf("After main\n");
}
int main(int argc, char **argv) {
   printf("In main\n");
   return 0;
}
 $ gcc -c foo.c
 $ ar rcs foo.a foo.o 
 $ gcc test.c foo.a
 $ ./a.out 
Before main
In main
After main
           

看一下動态庫:

$ g++ -c foo.c -o foo.o -fPIC
$ g++ -shared -fPIC -o libfoo.so foo.o                                                                                                                                                                         1 ↵
$ g++ test.c -L. -lfoo                
$ export LD_LIBRARY_PATH=`pwd`                                                                                                                                                                               127 ↵
$ ./a.out                     
foo called
Before main
In main
After main           

發現問題了,靜态連結的 foo.c 裡面的 __attribute__((constructor)) 并沒有執行。動态連結後是正确的。

原因是linker在靜态連結的時候,預設隻連結用到的符号,沒有用到的就不會拿過來了。對于上面的這種情況,__attribute__((constructor)) 屬性的子產品構造器就被 strip 了。

解決辦法是使用-Wl,--whole-archive 和 --no-whole-archive 标簽,顯式的辨別連結所有的符号。

$ g++ test.c -Wl,--whole-archive foo.a -Wl,--no-whole-archive
root@31-216:~/smartx/spdk 
 $ ./a.out 
Before main
foo called
In main
After main           
注意,-Wl,--whole-archive 中間不能有空格。

Done。

這個坑容易踩到,在此記錄一下。

原文連結:https://zhuanlan.zhihu.com/p/42814326

繼續閱讀