"디버깅을 통해 배우는 리눅스 커널의 구조와 원리": 라즈베리 파이 4B 와 최신 리눅스에서의 실습을 위한 변경점

아직 전권을 읽지 않았습니다. 매 챕터 끝날때마다 업데이트 하겠습니다 디버깅을 통해 배우는 리눅스 커널의 구조와 원리는 라즈베리 파이 3과 32비트 리눅스 4.19 버전에서의 코드와 스크립트를 사용합니다. 라즈베리 파이 4B와 최신 64비트 리눅스 버전 6.12 LTS 에서는 몇가지 다른점들이 있는데, 이 포스트에서는 그 차이점들과 원활한 실습을 위한 방법들을 소개합니다. 라즈베리 파이 OS 2024-11-19버전 (데비안 12)에서 리눅스 6.12 커널을 설치했습니다. 테스트된 하드웨어는 라즈베리 파이 4B 8GB 입니다. 2장 라즈베리 파이 설정 라즈베리 파이 4B는 BCM2711 SOC를 사용합니다. 또한 64비트 커널을 사용하기 위해선 $KERNEL을 kernel8로 설정해야 합니다. 커널 이미지와 모듈의 위치도 다른것에 주의하세요! 더 자세한 정보는 라즈베리 파이 문서를 참고해주세요. 2.3.3 라즈비안 리눅스 커널 빌드 build_rpi_kernel.sh #!/bin/bash echo "configure build output path" KERNEL_TOP_PATH="$( cd "$(dirname "$0")" ; pwd -P )" OUTPUT="$KERNEL_TOP_PATH/out" echo "$OUTPUT" KERNEL=kernel8 BUILD_LOG="$KERNEL_TOP_PATH/rpi_build_log.txt" echo "move to kernel source" cd linux echo "make defconfig" make O=$OUTPUT bcm2711_defconfig echo "kernel build" make O=$OUTPUT Image.gz modules dtbs -j6 2>&1 | tee $BUILD_LOG 2.3.4 라즈비안 리눅스 커널 설치 install_rpi_kernel_img.sh #!/bin/bash KERNEL_TOP_PATH="$( cd "$(dirname "$0")" ; pwd -P )" OUTPUT="$KERNEL_TOP_PATH/out" echo "$OUTPUT" KERNEL=kernel8 cd linux make O=$OUTPUT modules_install sudo cp /boot/firmware/$KERNEL.img /boot/firmware/$KERNEL-backup.img sudo cp $OUTPUT/arch/arm64/boot/Image.gz /boot/firmware/$KERNEL.img sudo cp $OUTPUT/arch/arm64/boot/dts/broadcom/*.dtb /boot/firmware/ sudo cp $OUTPUT/arch/arm64/boot/dts/overlays/*.dtb* /boot/firmware/overlays/ sudo cp $OUTPUT/arch/arm64/boot/dts/overlays/README /boot/firmware/overlays/ 2.3.5 전처리 코드 생성 build_preprocess_rpi_kernel.sh #!/bin/bash echo "configure build output path" KERNEL_TOP_PATH="$( cd "$(dirname "$0")" ; pwd -P )" OUTPUT="$KERNEL_TOP_PATH/out" echo "$OUTPUT" KERNEL=kernel8 BUILD_LOG="$KERNEL_TOP_PATH/rpi_preprocess_build_log.txt" PREPROCESS_FILE=$1 echo "build preprocessed file: $PREPROCESS_FILE"" echo "move to kernel source" cd linux echo "make defconfig" make O=$OUTPUT bcm2711_defconfig echo "kernel build" make $PREPROCESS_FILE O=$OUTPUT Image.gz modules dtbs -j6 2>&1 | tee $BUILD_LOG 3장 커널 디버깅과 코드 학습 3.1.2 디버깅과 코드 학습 능력 kernel/irq/proc.c noinline void rpi_get_interrupt_info(struct irqaction *action_p) { unsigned int irq_num = action_p->irq; void *irq_handler = NULL; if (action_p->handler) { irq_handler = (void*)action_p->handler; } if (irq_handler) { trace_printk("[%s] %d: %s, irq_handler: %pS \n", current->comm, irq_num, action_p->name, irq_handler); } } `noinline`이 없으면 컴파일러가 최적화를 위해 자동으로 함수를 인라이닝(inlining) 하게 됩니다. 그렇게 되면 함수 자체는 `/sys/kernel/debug/tracing/available_filter_function` 파일에서 트레이싱 가능한 함수로 나오지만 실제로는 트레시징 되지 않게 됩니다. 또한 컴파일 도중에 `-Wmissing-prototypes` 경고가 뜨게 되는데 무시해도 상관없습니다. 또한 `irq_trace_ftrace.sh`에서 11번째 줄 sh echo secondary_start_kernel > /sys/kernel/debug/tracing/set_ftrace_filter 는 최신 커널에서 더이상 트레이싱 불가능(`notrace`)하니 주석처리 해주세요.

Feb 22, 2025 - 07:15
 0
"디버깅을 통해 배우는 리눅스 커널의 구조와 원리": 라즈베리 파이 4B 와 최신 리눅스에서의 실습을 위한 변경점

아직 전권을 읽지 않았습니다. 매 챕터 끝날때마다 업데이트 하겠습니다

디버깅을 통해 배우는 리눅스 커널의 구조와 원리는 라즈베리 파이 3과 32비트 리눅스 4.19 버전에서의 코드와 스크립트를 사용합니다. 라즈베리 파이 4B와 최신 64비트 리눅스 버전 6.12 LTS 에서는 몇가지 다른점들이 있는데, 이 포스트에서는 그 차이점들과 원활한 실습을 위한 방법들을 소개합니다.

라즈베리 파이 OS 2024-11-19버전 (데비안 12)에서 리눅스 6.12 커널을 설치했습니다. 테스트된 하드웨어는 라즈베리 파이 4B 8GB 입니다.

2장 라즈베리 파이 설정

라즈베리 파이 4B는 BCM2711 SOC를 사용합니다. 또한 64비트 커널을 사용하기 위해선 $KERNELkernel8로 설정해야 합니다. 커널 이미지와 모듈의 위치도 다른것에 주의하세요!

더 자세한 정보는 라즈베리 파이 문서를 참고해주세요.

2.3.3 라즈비안 리눅스 커널 빌드

build_rpi_kernel.sh

#!/bin/bash

echo "configure build output path"

KERNEL_TOP_PATH="$( cd "$(dirname "$0")" ; pwd -P )"
OUTPUT="$KERNEL_TOP_PATH/out"
echo "$OUTPUT"

KERNEL=kernel8
BUILD_LOG="$KERNEL_TOP_PATH/rpi_build_log.txt"

echo "move to kernel source"
cd linux

echo "make defconfig"
make O=$OUTPUT bcm2711_defconfig

echo "kernel build"
make O=$OUTPUT Image.gz modules dtbs -j6 2>&1 | tee $BUILD_LOG

2.3.4 라즈비안 리눅스 커널 설치

install_rpi_kernel_img.sh

#!/bin/bash

KERNEL_TOP_PATH="$( cd "$(dirname "$0")" ; pwd -P )"
OUTPUT="$KERNEL_TOP_PATH/out"

echo "$OUTPUT"

KERNEL=kernel8

cd linux

make O=$OUTPUT modules_install
sudo cp /boot/firmware/$KERNEL.img /boot/firmware/$KERNEL-backup.img
sudo cp $OUTPUT/arch/arm64/boot/Image.gz /boot/firmware/$KERNEL.img
sudo cp $OUTPUT/arch/arm64/boot/dts/broadcom/*.dtb /boot/firmware/
sudo cp $OUTPUT/arch/arm64/boot/dts/overlays/*.dtb* /boot/firmware/overlays/
sudo cp $OUTPUT/arch/arm64/boot/dts/overlays/README /boot/firmware/overlays/

2.3.5 전처리 코드 생성

build_preprocess_rpi_kernel.sh

#!/bin/bash

echo "configure build output path"

KERNEL_TOP_PATH="$( cd "$(dirname "$0")" ; pwd -P )"
OUTPUT="$KERNEL_TOP_PATH/out"
echo "$OUTPUT"

KERNEL=kernel8
BUILD_LOG="$KERNEL_TOP_PATH/rpi_preprocess_build_log.txt"

PREPROCESS_FILE=$1
echo "build preprocessed file: $PREPROCESS_FILE""

echo "move to kernel source"
cd linux

echo "make defconfig"
make O=$OUTPUT bcm2711_defconfig

echo "kernel build"
make $PREPROCESS_FILE O=$OUTPUT Image.gz modules dtbs -j6 2>&1 | tee $BUILD_LOG

3장 커널 디버깅과 코드 학습

3.1.2 디버깅과 코드 학습 능력

kernel/irq/proc.c

noinline void rpi_get_interrupt_info(struct irqaction *action_p)
{
        unsigned int irq_num = action_p->irq;
        void *irq_handler = NULL;

        if (action_p->handler) {
                irq_handler = (void*)action_p->handler;
        }

        if (irq_handler) {
                trace_printk("[%s] %d: %s, irq_handler: %pS \n",
                                                current->comm, irq_num, action_p->name, irq_handler);
        }
}

`noinline`이 없으면 컴파일러가 최적화를 위해 자동으로 함수를 인라이닝(inlining) 하게 됩니다. 그렇게 되면 함수 자체는 `/sys/kernel/debug/tracing/available_filter_function` 파일에서 트레이싱 가능한 함수로 나오지만 실제로는 트레시징 되지 않게 됩니다.

또한 컴파일 도중에 `-Wmissing-prototypes` 경고가 뜨게 되는데 무시해도 상관없습니다.

또한 `irq_trace_ftrace.sh`에서 11번째 


sh
echo secondary_start_kernel > /sys/kernel/debug/tracing/set_ftrace_filter



는 최신 커널에서 더이상 트레이싱 불가능(`notrace`)하니 주석처리 해주세요.