Home  >  Article  >  Backend Development  >  Output the function call relationship during nginx execution

Output the function call relationship during nginx execution

WBOY
WBOYOriginal
2016-08-08 09:24:291279browse

添加源文件

首先在src/core/目录下添加两个文件,分别是my_debug.h和my_debug.c。

<code><span>#ifndef MY_DEBUG_LENKY_H</span><span>#define MY_DEBUG_LENKY_H</span><span>#include <stdio.h></span><span>void</span> enable_my_debug(<span>void</span>) __attribute__ ((no_instrument_function));
<span>void</span> disable_my_debug(<span>void</span>) __attribute__ ((no_instrument_function));
<span>int</span> get_my_debug_flag(<span>void</span>) __attribute__ ((no_instrument_function));
<span>void</span> set_my_debug_flag(<span>int</span>) __attribute__ ((no_instrument_function));
<span>void</span> main_constructor(<span>void</span>) __attribute__ ((no_instrument_function, constructor));
<span>void</span> main_destructor(<span>void</span>) __attribute__ ((no_instrument_function, destructor));
<span>void</span> __cyg_profile_func_enter(<span>void</span>*, <span>void</span>*) __attribute__ ((no_instrument_function));
<span>void</span> __cyg_profile_func_exit(<span>void</span>*, <span>void</span>*) __attribute__ ((no_instrument_function));


<span>#ifndef MY_DEBUG_MAIN</span>
extern<span> FILE </span>*my_debug_fd;
<span>#else</span>
FILE *my_debug_fd;
<span>#endif</span><span>#endif</span></code>
<code><span>#include "my_debug.h"</span><span>#<span>define</span> MY_DEBUG_FILE_PATH "/usr/local/nginx/sbin/mydebug.log"</span><span>int</span> _flag = <span>0</span>;

<span>#<span>define</span> open_my_debug_file() \</span>
    (my_debug_fd = fopen(MY_DEBUG_FILE_PATH, <span>"a"</span>))

<span>#<span>define</span> close_my_debug_file() \</span><span>do</span> { \
        <span>if</span> (NULL != my_debug_fd) { \
            fclose(my_debug_fd); \
        } \
    }<span>while</span> (<span>0</span>)

<span>#<span>define</span> my_debug_print(args, fmt...) \</span><span>do</span> { \
        <span>if</span> (<span>0</span> == _flag) { \
            <span>break</span>; \
        } \
        <span>if</span> (NULL == my_debug_fd && NULL == open_my_debug_file()) { \
            printf(<span>"Err: can not open output file.\n"</span>); \
            <span>break</span>; \
        } \
        fprintf(my_debug_fd, args, <span>##fmt); \</span>
        fflush(my_debug_fd); \
    } <span>while</span> (<span>0</span>)

<span>void</span> enable_my_debug(<span>void</span>)
{
    _flag = <span>1</span>;
}

<span>void</span> disable_my_debug(<span>void</span>)
{
    _flag = <span>0</span>;
}

<span>int</span> get_my_debug_flag(<span>void</span>)
{
    <span>return</span> _flag;
}

<span>void</span> set_my_debug_flag(<span>int</span> flag)
{
    _flag = flag;
}

<span>void</span> main_constructor(<span>void</span>)
{

}

<span>void</span> main_destructor(<span>void</span>)
{
    close_my_debug_file();
}

<span>void</span> __cyg_profile_func_enter(<span>void</span> *<span>this</span>, <span>void</span> *call)
{
    my_debug_print(<span>"Enter\n%p\n%p\n"</span>, call, <span>this</span>);
}

<span>void</span> __cyg_profile_func_exit(<span>void</span> *<span>this</span>, <span>void</span> *call)
{
    my_debug_print(<span>"Exit\n%p\n%p\n"</span>, call, <span>this</span>);
}</code>

修改Makefile

makefile有如下几个地方需要修改(加粗部分):
1. CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -finstrument-functions
2. CORE_DEPS = src/core/nginx.h \
src/core/my_debug.h \
3. HTTP_DEPS = src/http/ngx_http.h \
src/core/my_debug.h \
4. objs/nginx: objs/src/core/nginx.o \
objs/src/core/my_debug.o \
5. $(LINK) -o objs/nginx \
objs/src/core/my_debug.o \

将my_debug.h包含到源码中

需要修改如下两个地方:
1. 在ngx_core.h中添加:

<code><span>#include </span><span>"my_debug.h"</span></code>
  1. 在nginx.c中添加:
<code><span>#<span>define</span> MY_DEBUG_MAIN 1</span></code>

运行程序并用addr2line导出函数调用关系

运行程序:./objs/nginx,生成文件/usr/local/nginx/sbin/mydebug.log,路径是在my_debug.c中定义的。里面显示的只是函数的调用地址,可以写一个脚本addr2line.sh将地址转换为函数名。

<code><span>#! /bin/sh
</span><span>if</span> [ <span>$#</span> != <span>3</span> ]; <span>then</span><span>echo</span><span>'Usage: addr2line.sh executefile addressfile functionfile'</span><span>exit</span><span>fi</span>;

cat <span>$2</span> | <span>while</span><span>read</span> line
<span>do</span><span>if</span> [ <span>"<span>$line</span>"</span> = <span>'Enter'</span> ]; <span>then</span><span>read</span> line1
        <span>read</span> line2
<span>#       echo $line >> $3</span>
        addr2line <span>-e</span><span>$1</span><span>-f</span><span>$line1</span><span>-s</span> >> <span>$3</span><span>echo</span><span>"--->"</span> >> <span>$3</span>
        addr2line <span>-e</span><span>$1</span><span>-f</span><span>$line2</span><span>-s</span> | sed <span>'s/^/  /'</span> >> <span>$3</span><span>echo</span> >> <span>$3</span><span>elif</span> [ <span>"<span>$line</span>"</span> = <span>'Exit'</span> ]; <span>then</span><span>read</span> line1
        <span>read</span> line2
        addr2line <span>-e</span><span>$1</span><span>-f</span><span>$line2</span><span>-s</span> | sed <span>'s/^/  /'</span> >> <span>$3</span><span>echo</span><span>"<---"</span> >> <span>$3</span>
        addr2line <span>-e</span><span>$1</span><span>-f</span><span>$line1</span><span>-s</span> >> <span>$3</span><span>echo</span> >> <span>$3</span><span>fi</span>;
<span>done</span></span></code>

执行脚本:

<code>./addr2line.sh ./objs/nginx /usr/<span>local</span>/nginx/sbin/mydebug.<span>log</span> myfun.<span>log</span></code>

就可以在mydebug.log中看到从nginx启动开始调用的各函数之间的关系。
截取一部分如下:

<code><span>main</span><span>nginx</span><span>.c</span><span>:279</span><span>---</span>>
    <span>ngx_regex_init</span><span>ngx_regex</span><span>.c</span><span>:74</span><span>ngx_regex_init</span><span>ngx_regex</span><span>.c</span><span>:74</span>
<<span>---</span><span>main</span><span>nginx</span><span>.c</span><span>:279</span><span>main</span><span>nginx</span><span>.c</span><span>:313</span><span>---</span>>
    <span>ngx_os_init</span><span>ngx_posix_init</span><span>.c</span><span>:34</span><span>ngx_os_init</span><span>ngx_posix_init</span><span>.c</span><span>:38</span><span>---</span>>
    <span>ngx_os_specific_init</span><span>ngx_linux_init</span><span>.c</span><span>:35</span><span>ngx_os_specific_init</span><span>ngx_linux_init</span><span>.c</span><span>:35</span>
<<span>---</span><span>ngx_os_init</span><span>ngx_posix_init</span><span>.c</span><span>:38</span></code>

遇到的问题

1.我是在windows编辑shell脚本,因此文件格式是dos,可以在linux中用vi打开,在vi中用命令行查看:

<code><span>set</span> ff</code>

如果这样执行会出现错误:
/bin/sh^M: bad interpreter: No such file or directory
解决办法:
在vi中执行命令

<code><span>set</span> ff = unix</code>
  1. 在执行make命令时出现错误,
    no target ‘\’
    解决办法:
    在Makefile文件中‘\’表示不换行,但是我在’\’后面多加了空格,只要把空格删除就好了。

以上就介绍了 输出nginx执行过程中函数调用关系,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn