日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

关于ceph源码 backtrace 打印函数调用栈

發布時間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于ceph源码 backtrace 打印函数调用栈 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

當集中精力看一個問題的時候,時間久了就會有這樣一個狀態,天空飄來五個字,那都不算事
ceph源碼龐大的體量以及復雜的設計讓很多人望而卻步,尤其是大量的純虛函數更是讓讀者迷失在代碼的海洋,這個時候函數調用棧是一個救命的東西,因為它節約了你大量的重復查找的時間

查看最終效果
如下為我想要查看bluestore在處理shareblob的釋放邏輯中對put函數的調用者查看

2019-07-11 20:11:30.408525 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/root/ceph-osd(BlueStore::SharedBlob::print_stacktrace()+0x39) [0x7fe3dff055d9]
2019-07-11 20:11:30.408535 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/root/ceph-osd(BlueStore::SharedBlob::put()+0x2c) [0x7fe3dff217bc]
2019-07-11 20:11:30.408536 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/root/ceph-osd(std::_Rb_tree<boost::intrusive_ptr<BlueStore::SharedBlob>, boost::intrusive_ptr<BlueStore::SharedBlob>, std::_Identity<boost::intrusive_ptr<BlueStore::SharedBlob> >, std::less<boost::intrusive_ptr<BlueStore::SharedBlob> >, std::allocator<boost::intrusive_ptr<BlueStore::SharedBlob> > >::_M_erase(std::_Rb_tree_node<boost::intrusive_ptr<BlueStore::SharedBlob> >*)+0x39) [0x7fe3dff8d619]
2019-07-11 20:11:30.408537 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/root/ceph-osd(BlueStore::_txc_finish(BlueStore::TransContext*)+0xbb) [0x7fe3dff2a55b]
2019-07-11 20:11:30.408537 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/root/ceph-osd(BlueStore::_txc_state_proc(BlueStore::TransContext*)+0x216) [0x7fe3dff3c746]
2019-07-11 20:11:30.408538 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/root/ceph-osd(BlueStore::_kv_finalize_thread()+0x630) [0x7fe3dff3e180]
2019-07-11 20:11:30.408538 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/root/ceph-osd(BlueStore::KVFinalizeThread::entry()+0xd) [0x7fe3dff95d2d]
2019-07-11 20:11:30.408539 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/lib64/libpthread.so.0(+0x7df3) [0x7fe3dce62df3]
2019-07-11 20:11:30.408539 7fe3cc5db700  0 bluestore.sharedblob(0x7fe3edad09a0) print_stacktrace/lib64/libc.so.6(clone+0x6d) [0x7fe3dbf573dd]

直接就是一目了然,非常直觀。

ps:由于對更高級的systemtap打印調用棧失敗,只能退而求其次暫時來手動增加函數調用棧,后期會將該工具的使用詳細列舉補足該問題

backtrace()和backtrace_symbols()函數實現調用棧

這兩個函數linux下使用命令
man backtrace
man backtrace_symbols
能夠查看到函數的具體用法
包含函數頭文件:#include <execinfo.h>

  • int backtrace(void **buffer, int size); buffer參數用來動態存儲調用當前函數的函數指針(地址),size參數則表示當前存儲函數指針的數組最大容量。所以這里需要注意將這兩個參數容量預估好
  • char **backtrace_symbols(void *const *buffer, int size); 該函數用來將以上獲取到的函數地址轉為對應容量的字符串數組

代碼如下:

void print_stacktrace()
{int size = 16,i=0;void * array[16];int stack_num = backtrace(array, size);char ** stacktrace = backtrace_symbols(array, stack_num);for (; i < stack_num; ++i){printf("%s\n", stacktrace[i]); }free(stacktrace);
}

查看測試代碼 print_func_stack.c

#include<stdio.h>
#include <execinfo.h>
void print_stacktrace()
{int size = 16,i=0;void * array[16];int stack_num = backtrace(array, size);char ** stacktrace = backtrace_symbols(array, stack_num);for (; i < stack_num; ++i){printf("%s\n", stacktrace[i]);
//           ldout(coll->store->cct,0) << __func__ << stacktrace[i] << dendl;       }free(stacktrace);
}
int func3(int a)
{print_stacktrace();return a*a;
}
int func2(int b)
{int c=func3(b);return c;
}
int func1(int c)
{return func2(c*c);
}
int main()
{printf("after print stack ,result is %d\n",func1(2));return 0;
}

編譯gcc print_func_stack.c -rdynamic -o print_func_stack ,這里需要加上-rdynamic編譯參數,它可以連接所有符號,否則打印出來僅僅為16進制函數地址
執行如下,可以看到函數調用棧已經清晰打印

[root@node1 ~]# ./print_func_stack 
./print_func_stack(print_stacktrace+0x32) [0x400992]
./print_func_stack(func3+0x15) [0x400a04]
./print_func_stack(func2+0x15) [0x400a22]
./print_func_stack(func1+0x19) [0x400a43]
./print_func_stack(main+0xe) [0x400a53]
/lib64/libc.so.6(__libc_start_main+0xf5) [0x7f7c766b2af5]
./print_func_stack() [0x400899]
after print stack ,result is 16

ps:
如果代碼是C++代碼,則如上編譯出來的二進制文件是被manle的(即源碼標識被c++編譯器轉為了編譯器標識符ABI,會出現我們認為的亂碼),這里需要將輸出轉為demangle(即我們認識的源碼標識)。
類似如下:

/root/ceph-osd(_ZN9BlueStore10SharedBlob16print_stacktraceEv+0x2d) [0x7ff22948a5cd]
/root/ceph-osd(_ZN9BlueStore10SharedBlob3putEv+0x2c) [0x7ff2294a61bc]
/root/ceph-osd(_ZN9BlueStore6ExtentD1Ev+0xd1) [0x7ff229511bb1]
/root/ceph-osd(_ZN9BlueStore5Onode3putEv+0x96) [0x7ff2295120f6]
/root/ceph-osd(_ZN9BlueStore9TwoQCache5_trimEmm+0x365) [0x7ff2294b7b75]
/root/ceph-osd(_ZN9BlueStore5Cache8trim_allEv+0x30) [0x7ff229489a80]
/root/ceph-osd(_ZN9BlueStore12_flush_cacheEv+0x9f) [0x7ff2294b9d1f]
/root/ceph-osd(_ZN9BlueStore6umountEv+0x128) [0x7ff2294ba0b8]
/root/ceph-osd(_ZN3OSD8shutdownEv+0x1695) [0x7ff2290a48b5]
/root/ceph-osd(_ZN3OSD13handle_signalEi+0x11f) [0x7ff2290a518f]
/root/ceph-osd(_ZN13SignalHandler5entryEv+0x1d7) [0x7ff2295ebb17]

可以執行如下命令進行過濾
./print_func_stack |c++filt

更具體一點,我們想要查看打印出來的函數具體在哪個程序的哪一行,需要使用如下編譯方式
gcc print_func_stack.c -rdynamic -g -o print_func_stack 再增加-g 的gdb調試參數
執行如下命令就可以看到具體函數位置

[root@node1 ~]# ./print_func_stack 
./print_func_stack(print_stacktrace+0x32) [0x400992]
./print_func_stack(func3+0x15) [0x400a04]
./print_func_stack(func2+0x15) [0x400a22]
./print_func_stack(func1+0x19) [0x400a43]
./print_func_stack(main+0xe) [0x400a53]
/lib64/libc.so.6(__libc_start_main+0xf5) [0x7f287597daf5]
./print_func_stack() [0x400899]
after print stack ,result is 16
[root@node1 ~]# addr2line -a 0x400a04 -e print_func_stack -f
0x0000000000400a04
func3
/root/print_func_stack.c:18
[root@node1 ~]# addr2line -a 0x400a04 -e print_func_stack -f -C #該-C參數是將源碼轉為demangle形式打印,防止看到的是mangle的ABI字符
0x0000000000400a04
func3
/root/print_func_stack.c:18
ceph源碼添加函數調用棧

同樣的方式,將以上函數封裝到指定的類中,這里是為了不通類的debug日志方式不通,所以沒有定義為全局變量。我這里是直接聲明在SharedBlob大類中,所有該類對象都可以調用。定義很簡單

 1657 void BlueStore::SharedBlob::print_stacktrace()                  1658 {1659       int size = 16;1660       void * array[16];1661       int stack_num = backtrace(array, size);                   1662       char ** stacktrace = backtrace_symbols(array, stack_num);                                                                                                                                                                                                         1663       for (int i = 0; i < stack_num; ++i)                       1664       {1665 //           printf("%s\n", stacktrace[i]);                     1666            ldout(coll->store->cct,0) << __func__ << stacktrace[i] << dendl;       1667       }1668       free(stacktrace);                                         1669 }

直接將該函數放入bluestore.cc不同函數之中就可以進行調用棧打印。

總結

以上是生活随笔為你收集整理的关于ceph源码 backtrace 打印函数调用栈的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。