黄种人 發表於 2023-5-31 00:00:00

透视Linux内核,BPF神奇的Linux技术入门

<h2 id="h7a42537-PN6DR83h" data-id="h7a42537-PN6DR83h">
        一、前言
</h2>
<p data-id="pd157317-AT1O7xmN">
        作为一个coder,时不时会遇到性能问题,有时候明明看资源,cpu,io都占用不高,程序的性能就是上不去,真有一种想进入到计算机里面看看到底发生什么的冲突;还有优化性能的时候不知道整个系统的短板到底是哪一块,如何去优化它?
</p>
<p data-id="pd157317-VS7Jyuau">
        根本原因其实是对系统的内核不够了解,导致虽然有解决问题的激情和动力,但是总是难找到关键点,彷徨而不得其门。让我学习内核,却又望而退步,觉得难度还是太大,有没有不用深入了解系统内核,但是又能深入观察内核行为的办法那,这时候我发现了BPF和eBPF,通过它有了透视内核的能力,所以就开始了BPF学习之旅。
</p>
<h2 id="h7a42537-LZBc8J9c" data-id="h7a42537-LZBc8J9c">
        二、BPF是个什么
</h2>
<p data-id="pd157317-mKrkSrdR">
        BPF原来是Berkely Packet Filter(伯克利数据包过滤器)的缩写,原来是提升pcap过滤性能的,比当时最快的包过滤技术快20倍,只所以性能高,是因为它工作在内核中,避免包从内核态复制到用户态所以速度快,后来Alexei Starovoitov 大牛在2014年重新实现了BPF,将其扩展成了通用的执行引擎,称为eBPF,官方缩写仍是BPF。
</p>
<p data-id="pd157317-QmwHF0xU">
        简单解释BPF作用,BPF提供了一种当内核或应用特定事件发生时候,执行一段代码的能力。BPF 采用了虚拟机指令规范,所以也可以看一种虚拟机实现,使我们可以在不修改内核源码和重新编译的情况下,提供一种扩展内核的能力的方法。
</p>
<h2 id="h7a42537-T7nAMBA0" data-id="h7a42537-T7nAMBA0">
        三、BPF能干嘛
</h2>
<p data-id="pd157317-hbxyLggS">
        BPF程序不像一般程序可以独立运行,它是被动运行的,需要事件触发才能运行,有点类似js里面的监听,监听到按钮点击执行一小段代码。这些事件包括系统调用,内核跟踪,内核函数,用户函数,网络事件等。
</p>
<p data-id="pd157317-B1jdt0u6">
        具体能干嘛那,作用还是很强大,可以进行系统故障诊断,因为其有透视内核的能力;网络性能优化,因为它可以在内核态接收网络包,并做修改和转发;系统安全,因为它可以中断非法连接等;性能监控,因为其透视能力,可以查看函数耗费时间从而我们可以知道问题到底出在哪里。 如下图:
</p>
<p data-id="pb60e94d-9UWw8wFn">
        <img title="透视Linux内核,BPF神奇的Linux技术入门" alt="透视Linux内核,BPF神奇的Linux技术入门" src="https://zhuji.jb51.net/uploads/img/202305/3f8847ed2dfbad28304123f31486f8af.jpg"></p>
<h2 id="h7a42537-oWffVm6V" data-id="h7a42537-oWffVm6V">
        四、BPF如何工作
</h2>
<p data-id="pd157317-MCzlmeqi">
        经典的BPF的工作模式是用户使用BPF虚拟机的指令集定义过滤表达式,传递给内核,由解释器运行,使得包过滤器可以直接在内核态工作,避免向用户态复制数据,从而提升性能,比如tcpdump的BPF过滤指令实例如下:
</p>
<pre><span class="cm-bracket">[</span>root@localhost <span class="cm-operator">~</span><span class="cm-bracket">]</span># tcpdump <span class="cm-operator">-</span>d port <span class="cm-number">80</span> <span class="cm-bracket">(</span><span class="cm-number">000</span><span class="cm-bracket">)</span> ldh <span class="cm-bracket">[</span><span class="cm-number">12</span><span class="cm-bracket">]</span> <span class="cm-bracket">(</span><span class="cm-number">001</span><span class="cm-bracket">)</span> jeq      #0x86dd          jt <span class="cm-number">2</span> jf <span class="cm-number">10</span> <span class="cm-bracket">(</span><span class="cm-number">002</span><span class="cm-bracket">)</span> ldb <span class="cm-bracket">[</span><span class="cm-number">20</span><span class="cm-bracket">]</span> <span class="cm-bracket">(</span><span class="cm-number">003</span><span class="cm-bracket">)</span> jeq      #0x84            jt <span class="cm-number">6</span> jf <span class="cm-number">4</span> <span class="cm-bracket">(</span><span class="cm-number">004</span><span class="cm-bracket">)</span> jeq      #0x6             jt <span class="cm-number">6</span> jf <span class="cm-number">5</span> <span class="cm-bracket">(</span><span class="cm-number">005</span><span class="cm-bracket">)</span> jeq      #0x11            jt <span class="cm-number">6</span> jf <span class="cm-number">23</span> <span class="cm-bracket">(</span><span class="cm-number">006</span><span class="cm-bracket">)</span> ldh <span class="cm-bracket">[</span><span class="cm-number">54</span><span class="cm-bracket">]</span> <span class="cm-bracket">(</span><span class="cm-number">007</span><span class="cm-bracket">)</span> jeq      #0x50            jt <span class="cm-number">22</span> jf <span class="cm-number">8</span> <span class="cm-bracket">(</span><span class="cm-number">008</span><span class="cm-bracket">)</span> ldh <span class="cm-bracket">[</span><span class="cm-number">56</span><span class="cm-bracket">]</span> <span class="cm-bracket">(</span><span class="cm-number">009</span><span class="cm-bracket">)</span> jeq      #0x50            jt <span class="cm-number">22</span> jf <span class="cm-number">23</span> <span class="cm-bracket">(</span><span class="cm-number">010</span><span class="cm-bracket">)</span> jeq      #0x800         jt <span class="cm-number">11</span> jf <span class="cm-number">23</span> <span class="cm-bracket">(</span><span class="cm-number">011</span><span class="cm-bracket">)</span> ldb <span class="cm-bracket">[</span><span class="cm-number">23</span><span class="cm-bracket">]</span> <span class="cm-bracket">(</span><span class="cm-number">012</span><span class="cm-bracket">)</span> jeq      #0x84            jt <span class="cm-number">15</span> jf <span class="cm-number">13</span> <span class="cm-bracket">(</span><span class="cm-number">013</span><span class="cm-bracket">)</span> jeq      #0x6             jt <span class="cm-number">15</span> jf <span class="cm-number">14</span> <span class="cm-bracket">(</span><span class="cm-number">014</span><span class="cm-bracket">)</span> jeq      #0x11            jt <span class="cm-number">15</span> jf <span class="cm-number">23</span> <span class="cm-bracket">(</span><span class="cm-number">015</span><span class="cm-bracket">)</span> ldh <span class="cm-bracket">[</span><span class="cm-number">20</span><span class="cm-bracket">]</span> <span class="cm-bracket">(</span><span class="cm-number">016</span><span class="cm-bracket">)</span> jset   #0x1fff          jt <span class="cm-number">23</span> jf <span class="cm-number">17</span> <span class="cm-bracket">(</span><span class="cm-number">017</span><span class="cm-bracket">)</span> ldxb <span class="cm-number">4</span><span class="cm-operator">*</span><span class="cm-bracket">(</span><span class="cm-bracket">[</span><span class="cm-number">14</span><span class="cm-bracket">]</span><span class="cm-operator">&amp;</span><span class="cm-number">0xf</span><span class="cm-bracket">)</span> <span class="cm-bracket">(</span><span class="cm-number">018</span><span class="cm-bracket">)</span> ldh <span class="cm-bracket">[</span>x <span class="cm-operator">+</span> <span class="cm-number">14</span><span class="cm-bracket">]</span> <span class="cm-bracket">(</span><span class="cm-number">019</span><span class="cm-bracket">)</span> jeq      #0x50            jt <span class="cm-number">22</span> jf <span class="cm-number">20</span> <span class="cm-bracket">(</span><span class="cm-number">020</span><span class="cm-bracket">)</span> ldh <span class="cm-bracket">[</span>x <span class="cm-operator">+</span> <span class="cm-number">16</span><span class="cm-bracket">]</span> <span class="cm-bracket">(</span><span class="cm-number">021</span><span class="cm-bracket">)</span> jeq      #0x50            jt <span class="cm-number">22</span> jf <span class="cm-number">23</span> <span class="cm-bracket">(</span><span class="cm-number">022</span><span class="cm-bracket">)</span> ret      #262144 <span class="cm-bracket">(</span><span class="cm-number">023</span><span class="cm-bracket">)</span> ret      #0
</pre>
<p data-id="pd157317-xGtLkRBF">
        执行过程如下:
</p>
<p data-id="pb60e94d-RnTJnhk5">
        <img title="透视Linux内核,BPF神奇的Linux技术入门" alt="透视Linux内核,BPF神奇的Linux技术入门" src="https://zhuji.jb51.net/uploads/img/202305/a811bde7d169256e9901392f2f093952.jpg"></p>
<p data-id="pd157317-0KroGFEt">
        后来又一位大牛EricDumazet在2011年7月发布的Linux 3.0中增加了JIT(即时编译),性能比解释执行更快,多像java的虚拟机,可以解释执行也可以即时编译执行。
</p>
<p data-id="pd157317-Q79atKhA">
        现在BPF的执行过程如下示意图:
</p>
<p data-id="pb60e94d-K03bYbdT">
        <img title="透视Linux内核,BPF神奇的Linux技术入门" alt="透视Linux内核,BPF神奇的Linux技术入门" src="https://zhuji.jb51.net/uploads/img/202305/9e26e3f545014bfa1ec9dc44674fd543.jpg"></p>
<ul data-id="ucd67dc5-7e26Q2b2">
<li data-id="l20de63f-0UjNXS6D">
                编写eBPF 代码;
        </li>
        <li data-id="l20de63f-GQAhR4nb">
                将eBPF代码通过LLVM把编写的eBPF代码转成字节码;
        </li>
        <li data-id="l20de63f-2AgQbaQa">
                通过bpf系统调用提交给系统内核;
        </li>
        <li data-id="l20de63f-YRkHojXe">
                内核通过验证器对代码做安全性验证(包括对无界循环的检查);
        </li>
        <li data-id="l20de63f-Oqlhcbmh">
                只有校验通过的字节码才会提交到JIT进行编译成可以直接执行的机器指令;
        </li>
        <li data-id="l20de63f-3TLrBlVB">
                当事件发生时候,调用这些指令执行,将结果保存到map中;
        </li>
        <li data-id="l20de63f-4MSHVfMr">
                用户程序通过映射来获取执行结果。
        </li>
</ul>
<h2 id="h7a42537-e7AJZBVN" data-id="h7a42537-e7AJZBVN">
        五、BPF 和内核模块对比
</h2>
<p data-id="pd157317-7cwxcF6S">
        BPF程序会进行安全检查,内核模块可能会引入Bug。
</p>
<p data-id="pd157317-CA4pTBke">
        BPF程序不能随意调用内核函数,只能调用部分辅助函数。
</p>
<p data-id="pd157317-MRe0Nr29">
        BPF的栈空间最大为512个字节,不能扩大,只能借助map存储。
</p>
<p data-id="pd157317-yx6siXZa">
        BPF程序可以一次编译到处运行,因为它依赖的辅助函数,映射表,BPF指令集属于稳定的API。
</p>
<h2 id="h7a42537-VebMJUKQ" data-id="h7a42537-VebMJUKQ">
        六、编写BPF程序
</h2>
<h3 id="h0613ccc-gFtkXApA" data-id="h0613ccc-gFtkXApA">
        6.1 准备知识
</h3>
<p data-id="pd157317-vIQkZYNq">
        开发BPF指令显然不适合直接用BPF指令开发,所以大牛们开发了一些前端工具让我们可以更方便的开发,比如我们可以通过C来编写BPF程序,然后通过LLVM编译成BPF。
</p>
<p data-id="pd157317-AVtHlEdq">
        当然还是负载,又有了BCC和bpftrace。BCC即BPF Compiler Collection,提供了开发BPF跟踪程序的高级框架,提供编写内核BPF程序的C语言环境,同时提供了许多高级语言的接口,比如pyhton等。同时BCC中提供了很多BPF工具,让我们可以方便使用用于性能分析和故障分析,在开发BPF程序之前可以看看。
</p>
<p data-id="pd157317-kghtEmLU">
        bpftrace编写单行程序或短小脚本更加适合,BCC适合编写复杂的脚本和作为后台进程使用。libbcc和libbpf为两者提供底层支持。
</p>
<p data-id="pb60e94d-5YO6x4mM">
        <img title="透视Linux内核,BPF神奇的Linux技术入门" alt="透视Linux内核,BPF神奇的Linux技术入门" src="https://zhuji.jb51.net/uploads/img/202305/7e463b60781a569e2e87661c852bcfa6.jpg"></p>
<p data-id="pb60e94d-WnZFVIeY">
        BPF程序编写可以借助工具
</p>
<p data-id="pb60e94d-pZVOoIZH">
        <img title="透视Linux内核,BPF神奇的Linux技术入门" alt="透视Linux内核,BPF神奇的Linux技术入门" src="https://zhuji.jb51.net/uploads/img/202305/edbbb0f4e2012d120226b779747fa12c.jpg"></p>
<p data-id="pb60e94d-SrHDVw2Y">
        BCC开发的动态追踪工具集
</p>
<h3 id="h0613ccc-p4ATH6nP" data-id="h0613ccc-p4ATH6nP">
        6.2 环境准备
</h3>
<p data-id="pd157317-l1FyakfB">
        我的测试环境是centos8.5版本,内核版本为4.18,而BPF最好用5.x版本的内核需要先升级下。
</p>
<pre><span class="cm-bracket">[</span>root@localhost <span class="cm-operator">~</span><span class="cm-bracket">]</span># cat <span class="cm-operator">/</span>etc<span class="cm-operator">/</span>centos<span class="cm-operator">-</span>release
CentOS Linux release <span class="cm-number">8.5</span><span class="cm-variable-2">.2111</span> <span class="cm-bracket">[</span>root@localhost <span class="cm-operator">~</span><span class="cm-bracket">]</span># uname <span class="cm-operator">-</span>a
Linux localhost<span class="cm-variable-2">.localdomain</span> <span class="cm-number">4.18</span><span class="cm-variable-2">.0</span><span class="cm-operator">-</span><span class="cm-number">348.7</span><span class="cm-variable-2">.1</span><span class="cm-variable-2">.el8_5</span><span class="cm-variable-2">.x86_64</span> #1 SMP Wed Dec <span class="cm-number">22</span> <span class="cm-number">13</span><span class="cm-punctuation">:</span><span class="cm-number">25</span><span class="cm-punctuation">:</span><span class="cm-number">12</span> UTC <span class="cm-number">2021</span> x86_64 x86_64 x86_64 GNU<span class="cm-operator">/</span>Linux
</pre>
<p data-id="pd157317-O4lShbQ5">
        内核升级步骤:
</p>
<pre>#1. 到<span class="cm-bracket">[</span>https<span class="cm-punctuation">:</span><span class="cm-operator">//</span>www<span class="cm-variable-2">.kernel</span><span class="cm-variable-2">.org</span><span class="cm-operator">/</span><span class="cm-bracket">]</span><span class="cm-bracket">(</span>https<span class="cm-punctuation">:</span><span class="cm-operator">//</span>www<span class="cm-variable-2">.kernel</span><span class="cm-variable-2">.org</span><span class="cm-operator">/</span><span class="cm-bracket">)</span>查看稳定的内核版本为5<span class="cm-variable-2">.16</span><span class="cm-variable-2">.10</span> #2. 下载编译
wget https<span class="cm-punctuation">:</span><span class="cm-operator">//</span>cdn<span class="cm-variable-2">.kernel</span><span class="cm-variable-2">.org</span><span class="cm-operator">/</span>pub<span class="cm-operator">/</span>linux<span class="cm-operator">/</span>kernel<span class="cm-operator">/</span>v5<span class="cm-variable-2">.x</span><span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-variable-2">.tar</span><span class="cm-variable-2">.xz</span> tar xvf linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-variable-2">.tar</span><span class="cm-variable-2">.xz</span> cd linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span> uname <span class="cm-operator">-</span>a
cp <span class="cm-operator">/</span>boot<span class="cm-operator">/</span>config<span class="cm-operator">-</span><span class="cm-number">4.18</span><span class="cm-variable-2">.0</span><span class="cm-operator">-</span><span class="cm-number">348.7</span><span class="cm-variable-2">.1</span><span class="cm-variable-2">.el8_5</span><span class="cm-variable-2">.x86_64</span> <span class="cm-variable-2">.config</span> #注释掉CONFIG_SYSTEM_TRUSTED_KEYS
makemenuconfig
#进入界面按tab 选择Load 加载<span class="cm-variable-2">.config</span> ,在Save后即可用原来配置编译

#编译内核核心
make <span class="cm-operator">-</span>j <span class="cm-number">4</span> make modules_install
#安装内核核心
make install
grub2<span class="cm-operator">-</span><span class="cm-keyword">set</span><span class="cm-operator">-</span>default <span class="cm-number">0</span> #0表示 <span class="cm-operator">/</span>boot<span class="cm-operator">/</span>grub2<span class="cm-operator">/</span>grub<span class="cm-variable-2">.cfg</span> 文件中排在第一位的 menuentry 段
reboot
make modules_prepare
make script
make headers_install   INSTALL_HDR_PATH<span class="cm-operator">=/</span>usr<span class="cm-operator">/</span>include
#安装bpf 实例
make M<span class="cm-operator">=</span>samples<span class="cm-operator">/</span>bpf
</pre>
<p data-id="pd157317-WdiX4Px1">
        安装BPF相关库和工具:
</p>
<pre>yum install libbpf<span class="cm-operator">-</span>devel make clang llvm elfutils<span class="cm-operator">-</span>libelf<span class="cm-operator">-</span>devel bpftool bcc<span class="cm-operator">-</span>tools bcc<span class="cm-operator">-</span>devel
</pre>
<ul data-id="ucd67dc5-RF4XbiR7">
<li data-id="l20de63f-g4jMKl3L">
                llvm : 将eBPF程序编译成字节码工具。
        </li>
        <li data-id="l20de63f-5IeI22Wg">
                c代码构建工具make<span>。</span>
        </li>
        <li data-id="l20de63f-X55SbTOo">
                eBPF工具集BCC和它依赖的头文件。
        </li>
        <li data-id="l20de63f-PipD7fk0">
                libelf库以及ebpf管理工具ebpftool。
        </li>
        <li data-id="l20de63f-jH9iY0M8">
                用户程序通过BPF映射查询到BPF字节码的字节码运行结果。
        </li>
</ul>
<h3 id="h0613ccc-XN22i0lK" data-id="h0613ccc-XN22i0lK">
        6.3 依赖BCC开发BPF的helloworld
</h3>
<p data-id="pd157317-m1jIx1pB">
        步骤如下:
</p>
<p data-id="pd157317-uy24dqc9">
        用C语言开发一个eBPF程序;
</p>
<p data-id="pd157317-0GzfQX5g">
        用LLVM把eBPF程序编译成BPF字节码;
</p>
<p data-id="pd157317-Yz4GnFng">
        通过bpf系统调用,把BPF字节码提交给内核;
</p>
<p data-id="pd157317-VQxXYiSH">
        内核验证并运行BPF字节码,并把相应状态保存到BPF映射中;
</p>
<p data-id="pd157317-WMmvu8TK">
        用户程序通过 BPF 映射查询 BPF 字节码,得到执行结果;
</p>
<p data-id="pd157317-FDILRMe5">
        这个流程一般比较麻烦,可以利用BCC来简化,用python脚本加载BPF程序,编译为字节码,并通过系统调用将BPF字节码,运行BPF字节码;
</p>
<h4 id="hdf2c2dd-NFCrkjNd" data-id="hdf2c2dd-NFCrkjNd">
        6.3.1 用C开发一个eBPF程序
</h4>
<pre><span class="cm-builtin">int</span> hello<span class="cm-bracket">(</span>void <span class="cm-operator">*</span>ctx<span class="cm-bracket">)</span> <span class="cm-bracket">{</span> bpf_trace_printk<span class="cm-bracket">(</span><span class="cm-string">"Hello, World!"</span><span class="cm-bracket">)</span><span class="cm-punctuation">;</span> return <span class="cm-number">0</span><span class="cm-punctuation">;</span> <span class="cm-bracket">}</span> </pre>
<p data-id="pd157317-TC3DMQGw">
        bpf_trace_printk 是常用的BPF辅助函数,它就是简单的打印一个字符串;不过eBPF输出是内核调试文件:
</p>
<pre><span class="cm-operator">/</span>sys<span class="cm-operator">/</span>kernel<span class="cm-operator">/</span>debug<span class="cm-operator">/</span>tracing<span class="cm-operator">/</span>trace_pipe
</pre>
<h4 id="hdf2c2dd-JJaLlx1E" data-id="hdf2c2dd-JJaLlx1E">
        6.3.2 使用python和BCC开发BPF的加载程序
</h4>
<pre>#<span class="cm-operator">!/</span>usr<span class="cm-operator">/</span>bin<span class="cm-operator">/</span>env python3
# <span class="cm-number">1</span><span class="cm-bracket">)</span> 导入BCC库中的BPF模块 <span class="cm-keyword">from</span> bcc import BPF

# <span class="cm-number">2</span><span class="cm-bracket">)</span> 加载C程序开发的BPF程序
b <span class="cm-operator">=</span> BPF<span class="cm-bracket">(</span>src_file<span class="cm-operator">=</span><span class="cm-string">"hello.c"</span><span class="cm-bracket">)</span> # <span class="cm-number">3</span><span class="cm-bracket">)</span> 将此BPF程序挂载到内核探针,其中do_sys_openat2是系统调用openat 在内核实现
b<span class="cm-variable-2">.attach_kprobe</span><span class="cm-bracket">(</span>event<span class="cm-operator">=</span><span class="cm-string">"do_sys_openat2"</span><span class="cm-punctuation">,</span> fn_name<span class="cm-operator">=</span><span class="cm-string">"hello_world"</span><span class="cm-bracket">)</span> # <span class="cm-number">4</span><span class="cm-bracket">)</span> 读取和打印 <span class="cm-operator">/</span>sys<span class="cm-operator">/</span>kernel<span class="cm-operator">/</span>debug<span class="cm-operator">/</span>tracing<span class="cm-operator">/</span>trace_pipe
b<span class="cm-variable-2">.trace_print</span><span class="cm-bracket">(</span><span class="cm-bracket">)</span> </pre>
<p data-id="pd157317-4tsjUggc">
        运行查看:
</p>
<pre><span class="cm-operator">&gt;</span> python3 hello<span class="cm-variable-2">.py</span> b<span class="cm-string">'       pmdalinux-1298    d..316758.674383: bpf_trace_printk: Hello, World!'</span> b<span class="cm-string">'       pmdalinux-1298    d..316758.674395: bpf_trace_printk: Hello, World!'</span> b<span class="cm-string">'       pmdalinux-1298    d..316758.674410: bpf_trace_printk: Hello, World!'</span> b<span class="cm-string">'       pmdalinux-1298    d..316758.674422: bpf_trace_printk: Hello, World!'</span> b<span class="cm-string">'       pmdalinux-1298    d..316758.674426: bpf_trace_printk: Hello, World!'</span> b<span class="cm-string">'       python3-73326    d..316758.674859: bpf_trace_printk: Hello, World!'</span> b<span class="cm-string">'      irqbalance-942    d..316758.894331: bpf_trace_printk: Hello, World!'</span> b<span class="cm-string">'      irqbalance-942    d..316758.894593: bpf_trace_printk: Hello, World!'</span> </pre>
<h3 id="h0613ccc-qPTSWwq7" data-id="h0613ccc-qPTSWwq7">
        问题解决
</h3>
<h4 id="hdf2c2dd-wauzdZCx" data-id="hdf2c2dd-wauzdZCx">
        问题一:编译过程磁盘空间满了
</h4>
<pre>按照<span class="cm-bracket">[</span>https<span class="cm-punctuation">:</span><span class="cm-operator">//</span>blog<span class="cm-variable-2">.csdn</span><span class="cm-variable-2">.net</span><span class="cm-operator">/</span>xionglangs<span class="cm-operator">/</span>article<span class="cm-operator">/</span>details<span class="cm-operator">/</span><span class="cm-number">108866146</span><span class="cm-bracket">]</span>扩展磁盘;<span class="cm-bracket">(</span>https<span class="cm-punctuation">:</span><span class="cm-operator">//</span>blog<span class="cm-variable-2">.csdn</span><span class="cm-variable-2">.net</span><span class="cm-operator">/</span>xionglangs<span class="cm-operator">/</span>article<span class="cm-operator">/</span>details<span class="cm-operator">/</span><span class="cm-number">108866146</span><span class="cm-bracket">)</span> </pre>
<h4 id="hdf2c2dd-z2r7kddW" data-id="hdf2c2dd-z2r7kddW">
        问题二:make -j4 编译报错
</h4>
<pre>BTF<span class="cm-punctuation">:</span> <span class="cm-variable-2">.tmp_vmlinux</span><span class="cm-variable-2">.btf</span><span class="cm-punctuation">:</span> pahole <span class="cm-bracket">(</span>pahole<span class="cm-bracket">)</span> <span class="cm-keyword">is</span> <span class="cm-keyword">not</span> available
Failed to generate BTF for vmlinux
Try to disable CONFIG_DEBUG_INFO_BTF
make<span class="cm-punctuation">:</span> <span class="cm-operator">***</span> <span class="cm-bracket">[</span>Makefile<span class="cm-punctuation">:</span><span class="cm-number">1106</span><span class="cm-punctuation">:</span> vmlinux<span class="cm-bracket">]</span> Error <span class="cm-number">1</span> </pre>
<p data-id="pd157317-vt9yFVKQ">
        解决办法: 注释掉.config中的CONFIG_DEBUG_INFO_BTF 或 yum install dwarves
</p>
<h4 id="hdf2c2dd-dno3YQSD" data-id="hdf2c2dd-dno3YQSD">
        问题三:编译需要支持bpf
</h4>
<p data-id="pd157317-7ObUHCxZ">
        编译内核的时候bpf的编译选项打开,在.config文件中添加或修改
</p>
<pre> 编译内核的时候bpf的编译选项打开,在<span class="cm-variable-2">.config</span>文件中添加或修改
CONFIG_CGROUP_BPF<span class="cm-operator">=</span>y
CONFIG_BPF<span class="cm-operator">=</span>y
CONFIG_BPF_SYSCALL<span class="cm-operator">=</span>y
CONFIG_NET_SCH_INGRESS<span class="cm-operator">=</span>m
CONFIG_NET_CLS_BPF<span class="cm-operator">=</span>m
CONFIG_NET_CLS_ACT<span class="cm-operator">=</span>y
CONFIG_BPF_JIT<span class="cm-operator">=</span>y
CONFIG_LWTUNNEL_BPF<span class="cm-operator">=</span>y
CONFIG_HAVE_EBPF_JIT<span class="cm-operator">=</span>y
CONFIG_BPF_EVENTS<span class="cm-operator">=</span>y
CONFIG_TEST_BPF<span class="cm-operator">=</span>m
</pre>
<h4 id="hdf2c2dd-XVypLpr4" data-id="hdf2c2dd-XVypLpr4">
        问题四:make M=samples/bpf报错
</h4>
<pre><span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">//</span>bootstrap<span class="cm-operator">/</span>libbpf<span class="cm-operator">//</span>include<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpf_helper_defs<span class="cm-variable-2">.h</span><span class="cm-punctuation">:</span><span class="cm-number">322</span><span class="cm-punctuation">:</span><span class="cm-number">63</span><span class="cm-punctuation">:</span> error<span class="cm-punctuation">:</span> <span class="cm-atom">unknown</span> type name <span class="cm-string">'__u32'</span> static <span class="cm-builtin">long</span> <span class="cm-bracket">(</span><span class="cm-operator">*</span>bpf_tail_call<span class="cm-bracket">)</span><span class="cm-bracket">(</span>void <span class="cm-operator">*</span>ctx<span class="cm-punctuation">,</span> void <span class="cm-operator">*</span>prog_array_map<span class="cm-punctuation">,</span> __u32 index<span class="cm-bracket">)</span> <span class="cm-operator">=</span> <span class="cm-bracket">(</span>void <span class="cm-operator">*</span><span class="cm-bracket">)</span> <span class="cm-number">12</span><span class="cm-punctuation">;</span> <span class="cm-operator">^</span> <span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">//</span>bootstrap<span class="cm-operator">/</span>libbpf<span class="cm-operator">//</span>include<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpf_helper_defs<span class="cm-variable-2">.h</span><span class="cm-punctuation">:</span><span class="cm-number">350</span><span class="cm-punctuation">:</span><span class="cm-number">58</span><span class="cm-punctuation">:</span> error<span class="cm-punctuation">:</span> <span class="cm-atom">unknown</span> type name <span class="cm-string">'__u32'</span> static <span class="cm-builtin">long</span> <span class="cm-bracket">(</span><span class="cm-operator">*</span>bpf_clone_redirect<span class="cm-bracket">)</span><span class="cm-bracket">(</span>struct __sk_buff <span class="cm-operator">*</span>skb<span class="cm-punctuation">,</span> __u32 ifindex<span class="cm-punctuation">,</span> __u64 flags<span class="cm-bracket">)</span> <span class="cm-operator">=</span> <span class="cm-bracket">(</span>void <span class="cm-operator">*</span><span class="cm-bracket">)</span> <span class="cm-number">13</span><span class="cm-punctuation">;</span> <span class="cm-operator">^</span> fatal error<span class="cm-punctuation">:</span> too many errors emitted<span class="cm-punctuation">,</span> stopping now <span class="cm-bracket">[</span><span class="cm-operator">-</span>ferror<span class="cm-operator">-</span><span class="cm-keyword">limit</span><span class="cm-operator">=</span><span class="cm-bracket">]</span><span class="cm-number">1</span>. make M<span class="cm-operator">=</span>samples<span class="cm-operator">/</span>bpf报错 <span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">//</span>bootstrap<span class="cm-operator">/</span>libbpf<span class="cm-operator">//</span>include<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpf_helper_defs<span class="cm-variable-2">.h</span><span class="cm-punctuation">:</span><span class="cm-number">322</span><span class="cm-punctuation">:</span><span class="cm-number">63</span><span class="cm-punctuation">:</span> error<span class="cm-punctuation">:</span> <span class="cm-atom">unknown</span> type name <span class="cm-string">'__u32'</span> static <span class="cm-builtin">long</span> <span class="cm-bracket">(</span><span class="cm-operator">*</span>bpf_tail_call<span class="cm-bracket">)</span><span class="cm-bracket">(</span>void <span class="cm-operator">*</span>ctx<span class="cm-punctuation">,</span> void <span class="cm-operator">*</span>prog_array_map<span class="cm-punctuation">,</span> __u32 index<span class="cm-bracket">)</span> <span class="cm-operator">=</span> <span class="cm-bracket">(</span>void <span class="cm-operator">*</span><span class="cm-bracket">)</span> <span class="cm-number">12</span><span class="cm-punctuation">;</span> <span class="cm-operator">^</span> <span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">//</span>bootstrap<span class="cm-operator">/</span>libbpf<span class="cm-operator">//</span>include<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpf_helper_defs<span class="cm-variable-2">.h</span><span class="cm-punctuation">:</span><span class="cm-number">350</span><span class="cm-punctuation">:</span><span class="cm-number">58</span><span class="cm-punctuation">:</span> error<span class="cm-punctuation">:</span> <span class="cm-atom">unknown</span> type name <span class="cm-string">'__u32'</span> static <span class="cm-builtin">long</span> <span class="cm-bracket">(</span><span class="cm-operator">*</span>bpf_clone_redirect<span class="cm-bracket">)</span><span class="cm-bracket">(</span>struct __sk_buff <span class="cm-operator">*</span>skb<span class="cm-punctuation">,</span> __u32 ifindex<span class="cm-punctuation">,</span> __u64 flags<span class="cm-bracket">)</span> <span class="cm-operator">=</span> <span class="cm-bracket">(</span>void <span class="cm-operator">*</span><span class="cm-bracket">)</span> <span class="cm-number">13</span><span class="cm-punctuation">;</span> <span class="cm-operator">^</span> fatal error<span class="cm-punctuation">:</span> too many errors emitted<span class="cm-punctuation">,</span> stopping now <span class="cm-bracket">[</span><span class="cm-operator">-</span>ferror<span class="cm-operator">-</span><span class="cm-keyword">limit</span><span class="cm-operator">=</span><span class="cm-bracket">]</span> </pre>
<h4 id="hdf2c2dd-tfDADfPy" data-id="hdf2c2dd-tfDADfPy">
        解决办法:
</h4>
<pre>vim <span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">//</span>bootstrap<span class="cm-operator">/</span>libbpf<span class="cm-operator">//</span>include<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpf_helper_defs<span class="cm-variable-2">.h</span> 添加头文件:
#include <span class="cm-operator">&lt;</span>asm<span class="cm-operator">/</span>types<span class="cm-variable-2">.h</span><span class="cm-operator">&gt;</span> #include <span class="cm-operator">&lt;</span>linux<span class="cm-operator">/</span>types<span class="cm-variable-2">.h</span><span class="cm-operator">&gt;</span> </pre>
<h4 id="hdf2c2dd-xTg2zqrB" data-id="hdf2c2dd-xTg2zqrB">
        问题五:failed to load BTF from /root/core/linux-5.16.10/vmlinux: No such file or directory
</h4>
<pre>Error<span class="cm-punctuation">:</span> failed to load BTF <span class="cm-keyword">from</span> <span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>vmlinux<span class="cm-punctuation">:</span> No such file <span class="cm-keyword">or</span> directory
make<span class="cm-bracket">[</span><span class="cm-number">2</span><span class="cm-bracket">]</span><span class="cm-punctuation">:</span> <span class="cm-operator">***</span> <span class="cm-bracket">[</span>Makefile<span class="cm-punctuation">:</span><span class="cm-number">179</span>:<span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">/</span>vmlinux<span class="cm-variable-2">.h</span><span class="cm-bracket">]</span> 错误 <span class="cm-number">2</span> make<span class="cm-bracket">[</span><span class="cm-number">1</span><span class="cm-bracket">]</span><span class="cm-punctuation">:</span> <span class="cm-operator">***</span> <span class="cm-bracket">[</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>Makefile<span class="cm-punctuation">:</span><span class="cm-number">296</span>:<span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">/</span>bpftool<span class="cm-bracket">]</span> 错误 <span class="cm-number">2</span> make<span class="cm-punctuation">:</span> <span class="cm-operator">***</span> <span class="cm-bracket">[</span>Makefile<span class="cm-punctuation">:</span><span class="cm-number">1846</span>:samples<span class="cm-operator">/</span>bpf<span class="cm-bracket">]</span> 错误 <span class="cm-number">2</span> <span class="cm-bracket">[</span>root@localhost linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-bracket">]</span>#
</pre>
<p data-id="pd157317-JClyyseX">
        更改.config 配置:
</p>
<pre>CONFIG_DEBUG_INFO_BTF<span class="cm-operator">=</span>y
make <span class="cm-operator">-</span>j4
</pre>
<h4 id="hdf2c2dd-mumNn49I" data-id="hdf2c2dd-mumNn49I">
        问题六:fatal error: 'gnu/stubs-32.h' file not found
</h4>
<pre>make<span class="cm-bracket">[</span><span class="cm-number">2</span><span class="cm-bracket">]</span><span class="cm-punctuation">:</span> <span class="cm-operator">***</span> <span class="cm-bracket">[</span>Makefile<span class="cm-punctuation">:</span><span class="cm-number">179</span>:<span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">/</span>vmlinux<span class="cm-variable-2">.h</span><span class="cm-bracket">]</span> 错误 <span class="cm-number">2</span> make<span class="cm-bracket">[</span><span class="cm-number">1</span><span class="cm-bracket">]</span><span class="cm-punctuation">:</span> <span class="cm-operator">***</span> <span class="cm-bracket">[</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>Makefile<span class="cm-punctuation">:</span><span class="cm-number">296</span>:<span class="cm-operator">/</span>root<span class="cm-operator">/</span>core<span class="cm-operator">/</span>linux<span class="cm-operator">-</span><span class="cm-number">5.16</span><span class="cm-variable-2">.10</span><span class="cm-operator">/</span>samples<span class="cm-operator">/</span>bpf<span class="cm-operator">/</span>bpftool<span class="cm-operator">/</span>bpftool<span class="cm-bracket">]</span> 错误 <span class="cm-number">2</span> make<span class="cm-punctuation">:</span> <span class="cm-operator">***</span> <span class="cm-bracket">[</span>Makefile<span class="cm-punctuation">:</span><span class="cm-number">1846</span>:samples<span class="cm-operator">/</span>bpf<span class="cm-bracket">]</span> 错误 <span class="cm-number">2</span> </pre>
<h3 id="h0613ccc-faiAjqYm" data-id="h0613ccc-faiAjqYm">
        参考
</h3>
<p data-id="pd157317-CeuPLcYi">
        详细介绍了BPF程序编译生成字节码过程:https://www.cnblogs.com/lfri/p/15402973.html
</p>
<p data-id="pd157317-ouo3VlGk">
        https://maao.cloud/2021/03/01/%E7%AC%94%E8%AE%B0-BPF-and-XDP-Reference-Guide-cilium/#LLVM](https://maao.cloud/2021/03/01/%E7%AC%94%E8%AE%B0-BPF-and-XDP-Reference-Guide-cilium/#LLVM
</p>
<p data-id="pd157317-yJvjHfch">
        [技术|深入理解 BPF:一个阅读清单 (linux.cn)](https://linux.cn/article-9507-1.html)
</p>
<p>原文地址:https://www.toutiao.com/i7066702562270953996/</p>
頁: [1]
查看完整版本: 透视Linux内核,BPF神奇的Linux技术入门