我正在尝试在基于 ARM64 Ubuntu 20.04 映像的 Docker 容器内编译 eBPF 程序。我遇到编译错误,其中
clang
编译器无法找到 __u64
类型的定义,该定义应由内核标头提供。这是我收到的错误:
/usr/include/bpf/bpf_helper_defs.h:78:90: error: unknown type name '__u64'
static long (* const bpf_map_update_elem)(void *map, const void *key, const void *value, __u64 flags) = (void *) 2;
^
我已经安装了
linux-headers-${KERNEL_VERSION}
软件包并设置了 clang 的包含路径,如下所示:
RUN clang -O2 -target bpf \
-I/usr/src/linux-headers-${KERNEL_VERSION}/include \
-I/usr/src/linux-headers-${KERNEL_VERSION}/include/uapi \
-I/usr/src/linux-headers-${KERNEL_VERSION}/arch/arm64/include \
-I/usr/include/aarch64-linux-gnu \
-I/usr/include/aarch64-linux-gnu/asm \
-I/usr/include/aarch64-linux-gnu/asm-generic \
-I/usr/include/bpf \
-c ebpf_program.c -o ebpf_program.o
我还创建了符号链接以确保正确引用
asm
和 asm-generic
目录:
RUN ln -s /usr/include/aarch64-linux-gnu/asm /usr/include/asm
RUN ln -s /usr/include/aarch64-linux-gnu/asm-generic /usr/include/asm-generic
clang
编译器仍然找不到asm/types.h
文件。我已验证该文件存在并且可以在容器中访问。这是我通过 SSH 连接到容器时的输出:
root@container:/usr/include/aarch64-linux-gnu/asm# cat types.h
#include <asm-generic/types.h>
这是我完整的 Dockerfile:
# Use a base image that supports ARM64 architecture for Apple Silicon (local machines)
FROM --platform=linux/arm64 ubuntu:20.04
# Use ARG to specify the kernel version, allowing for flexibility
ARG KERNEL_VERSION=5.4.0-174-generic
ARG DEBIAN_FRONTEND=noninteractive
# Install dependencies
RUN apt-get update && apt-get install -y \
bpfcc-tools \
clang \
llvm \
libelf-dev \
zlib1g-dev \
gcc \
iproute2 \
git \
curl \
ca-certificates \
linux-libc-dev \
make \
pkg-config \
&& apt-get clean
# Install a specific version of the Linux kernel headers
RUN apt-get install -y linux-headers-${KERNEL_VERSION}
# Install Go for ARM64
RUN curl -OL https://golang.org/dl/go1.21.0.linux-arm64.tar.gz \
&& tar -C /usr/local -xzf go1.21.0.linux-arm64.tar.gz \
&& rm go1.21.0.linux-arm64.tar.gz
# Set environment variables for Go
ENV PATH=$PATH:/usr/local/go/bin
ENV GOPATH=/go
ENV PATH=$PATH:$GOPATH/bin
# Copy your Go application source code and module files into the container
COPY src /go/src/go_user_agent
# Set the working directory to the Go user agent script's location
WORKDIR /go/src/go_user_agent/
# Clone the libbpf repository and build it
RUN git clone https://github.com/libbpf/libbpf.git /usr/src/libbpf && \
cd /usr/src/libbpf/src && \
make && \
make install
# Create a symbolic link from /usr/include/aarch64-linux-gnu/asm to /usr/include/asm
RUN ln -s /usr/include/aarch64-linux-gnu/asm /usr/include/asm
# Create a symbolic link from /usr/include/aarch64-linux-gnu/asm-generic to /usr/include/asm-generic
RUN ln -s /usr/include/aarch64-linux-gnu/asm-generic /usr/include/asm-generic
# Set the KERNEL_HEADERS_DIR environment variable to the path of the installed kernel headers
ENV KERNEL_HEADERS_DIR=/usr/src/linux-headers-${KERNEL_VERSION}
# Compile the eBPF program using the correct include paths
RUN clang -O2 -target bpf \
-I$KERNEL_HEADERS_DIR/include \
-I$KERNEL_HEADERS_DIR/include/linux \
-I$KERNEL_HEADERS_DIR/include/uapi \
-I$KERNEL_HEADERS_DIR/arch/arm64/include \
-I/usr/include/aarch64-linux-gnu \
-I/usr/include/asm-generic \
-I/usr/include/bpf \
-c ebpf_program.c -o ebpf_program.o
# Download dependencies
RUN go get -d -v
# Run tests and benchmarks
RUN go test -v ./... # Run all tests
# Run benchmarks and capture CPU profiles
RUN go test -bench . -benchmem -cpuprofile cpu.prof -o bench.test
# Build the Go user agent script
RUN go build -o go_user_agent
# Command to run the user agent script
CMD ["./go_user_agent"]
我陷入困境,不知道还能做什么来解决这个问题。有没有人遇到过类似的问题,或者您可以提供可能出现问题的指导吗?
您是否曾经在 C 文件中包含
并且它应该放在 include bpf_helper_defs.h 之前
__u64
类型是Linux内核头文件中定义的基本无符号64位整数类型,通常为asm/types.h
或linux/types.h
等类型。如果clang
找不到,问题往往在于如何设置“包含路径”,或者如何安装和引用内核头。
在“内核数据类型 u8、u16、u32、u64 未解决”之后,问题出在编译与依赖这些数据类型的无线子系统 (mac80211) 相关的文件。建议的决议提到
<linux/types.h>
应自动包含 <asm/types.h>
,这使得显式包含 <asm-generic/types.h>
变得不必要,并且可能会带来可移植性问题。
因此请确保在
使用其中定义的类型之前包含(直接或间接)
linux/types.h
。
类似:
RUN clang -O2 -target bpf \
-I/usr/src/linux-headers-${KERNEL_VERSION}/include \
-I/usr/src/linux-headers-${KERNEL_VERSION}/arch/arm64/include \
-I/usr/src/linux-headers-${KERNEL_VERSION}/include/uapi \
-I/usr/src/linux-headers-${KERNEL_VERSION}/include/generated/uapi \
-I/usr/include/aarch64-linux-gnu \ # Adjust based on your architecture
-c ebpf_program.c -o ebpf_program.o
虽然您可能会想直接包含
<asm-generic/types.h>
来解决问题,但正如超级用户答案中提到的,通常不建议这样做。首选方法是依赖从 linux/types.h
开始的包含层次结构,这确保了不同内核版本和架构之间的可移植性和一致性。
如此线程中所述,
clang
选项-target bpf
可能会阻止找到asm/types.h
。asm/types.h
)位于以系统体系结构三元组命名的目录中(例如,对于 x86_64 系统为 /usr/include/x86_64-linux-gnu/
)。当使用 -target bpf
编译 BPF 时,clang
不会自动包含这些特定于架构的路径,从而导致定义缺失。
确保安装gcc-multilib
(RUN apt-get install -y gcc-multilib
)
虽然这些解决方法的直接适用性可能会根据您的特定 Docker 环境和您的目标架构(ARM64,如 Dockerfile 中所述)而有所不同,但基本原则和方法应该有助于解决编译问题
__u64
。