BSP大作业

[BSP前置培养大作业.pdf](H:\123\新建文件夹\WeChat Files\wxid_m7uts4kc8omo22\FileStorage\TempFromPhone\BSP前置培养大作业.pdf)

虚拟机配置Ubuntu20.04

虚拟机配置Ubuntu20.04新手全流程【其他系统版本安装同理】_哔哩哔哩_bilibili

搭建qemu

无需开发板,8分钟通过qemu搭建嵌入式linux自学环境_哔哩哔哩_bilibili

配置完后

安装qemu

1
wget https://download.qemu.org/qemu-9.2.4.tar.xz

解压

1
tar xJf qemu-9.2.4.tar.xz.tar.xz

报错 安装gcc

1
sudo apt install gcc

ubuntu20.04源码编译安装qemu(qemu8.2)_either install ensurepip, or alleviate the need fo-CSDN博客

安装一些基础配置

(35 封私信 / 14 条消息) qemu源码编译(完整图文教程) - 知乎

image-20250612135929025

image-20250612135943560

vscode+bear+clangd实现阅读代码精准跳转

有其他版本吗 这个文件夹

1我已经准备好了 大概需要多久 已经在编译了

2也准备好了

3.编译完成了 qumu已经启动了

做一个启动文件把 在这

qumu在/home/linqiutian/workspace/

启动脚本 方式

qemu-system-aarch64
-machine virt
-cpu cortex-a57
-m 2G
-kernel /home/linqiutian/workspace/linux/arch/arm64/boot/Image
-initrd /home/linqiutian/workspace/initramfs_arm64.img
-append “console=ttyAMA0 root=/dev/ram rdinit=/sbin/init”
-fsdev local,id=fsdev0,path=/home/linqiutian/workspace/hello,security_model=none
-device virtio-9p-pci,fsdev=fsdev0,mount_tag=hostshare
-nographic

挂载共享空间

mkdir -p /mnt/share
mount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt/share

为了正确编译驱动模块,我需要知道QEMU虚拟机中v5.10内核的源代码路径。请提供以下信息:

  1. QEMU虚拟机中v5.10内核源代码的完整路径 /home/linqiutian/workspace/linux

是要在qemu make 还是在这里make

在主机环境为什么要编译内核环境?

QEMU共享文件夹设置完整流程

  1. 主机端准备

  2. 创建共享目录:

mkdir -p /home/linqiutian/workspace/qemu_shared
cp -r /home/linqiutian/workspace/helloDev/*/home/linqiutian/workspace/qemu_shared/

  1. 准备QEMU启动命令:

qemu-system-x86_64
-kernel /path/to/vmlinuz-5.10
-initrd /path/to/initrd.img
-append “root=/dev/sda1 console=ttyS0”
-hda /path/to/qemu-image.qcow2
-fsdev local,id=share_dev,path=/home/linqiutian/workspace/qemu_shared,security_model=none
-device virtio-9p-pci,fsdev=share_dev,mount_tag=hostshare
-nographic
注意:请替换/path/to/为实际的路径。

  1. QEMU虚拟机内部操作

  2. 登录QEMU后创建挂载点:

mkdir -p /mnt/hostshare
2. 挂载共享文件夹:

mount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt/hostshare
3. 验证挂载:

ls /mnt/hostshare
3. 编译内核模块

  1. 进入共享目录:

cd /mnt/hostshare
2. 清理之前的编译(如有需要):

make clean
3. 编译模块:

make
4. 使用说明

  1. 主机端修改文件会自动同步到QEMU中

  2. 编译生成的.ko文件也会出现在主机的共享目录中

  3. 卸载共享文件夹(退出QEMU前):

umount /mnt/hostshare3

/mnt/hostshare # mknod /dev/hello_dev c 511 0
/mnt/hostshare # chmod 666 /dev/hello_dev
/mnt/hostshare # echo “Test message” > /dev/hello_dev
[ 624.427209] Hello device opened
sh: write error: Invalid argument
[ 624.437116] Hello device closed
/mnt/hostshare # dmesg | tail
[ 0.969666] with arguments:
[ 0.969690] /sbin/init
[ 0.969712] with environment:
[ 0.969730] HOME=/
[ 0.969740] TERM=linux
[ 485.529205] random: fast init done
[ 489.339214] hello_dev: loading out-of-tree module taints kernel.
[ 489.346637] Hello device registered with major number 511
[ 624.427209] Hello device opened
[ 624.437116] Hello device closed

从测试结果来看,内核模块基本工作正常,但存在一个问题:

  1. 成功部分:

设备节点创建成功 (/dev/hello_dev)
模块正确响应了open/close操作
主设备号511正确注册
2. 问题部分:

写入时出现Invalid argument错误
这表明驱动程序的write操作没有正确处理输入
3. 原因分析:

可能是驱动中没有实现write操作
或者write操作返回了错误值
也可能是缓冲区处理有问题
4. 解决方案:

需要检查驱动代码中的write函数实现
确保正确处理用户空间数据

需要使qemu有root权限,所以在启动时需要 使⽤sudo启动 arm64 root启动

sudo qemu-system-aarch64
-M virt
-cpu cortex-a53
-kernel /home/linqiutian/workspace/linux/arch/arm64/boot/Image.gz
-initrd /home/linqiutian/workspace/initramfs_arm64.img
-nographic
-serial mon:stdio
-append “console=ttyAMA0”
-fsdev local,security_model=passthrough,id=fsdev0,path=/home/linqiutian/workspace/qemu_shared
-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare

2.0

sudo qemu-system-aarch64
-M virt
-cpu cortex-a53
-kernel /home/wangbeiy/workspace/linux/arch/arm64/boot/Image.gz
-initrd /home/wangbeiy/workspace/initramfs_arm64.img
-nographic
-serial mon:stdio
-append “console=ttyAMA0”
-fsdev local,security_model=passthrough,id=fsdev0,path=/home/wangbeiy/workspace/qemu_shared
-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare

guest启动后需要⼿动mount该共享⽬录

创建专用挂载点目录:

mkdir /hostshare
2. 挂载宿主机共享目录:

mount -t 9p -o trans=virtio,version=9p2000.L hostshare /hostshare
3. 验证挂载是否成功:

ls /hostshare

要解决内核配置问题,请按照以下步骤操作:

  1. 首先进入内核源代码目录:

cd /home/linqiutian/workspace/linux
2. 生成内核配置文件(使用当前运行内核的配置):

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- oldconfig
3. 准备内核编译环境:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- prepare
4. 现在可以返回模块目录重新编译:

cd /path/to/module
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -C /home/linqiutian/workspace/linux M=$PWD modules

  1. 如果仍然遇到配置问题,可能需要:

从运行中的内核获取配置:
zcat /proc/config.gz > /home/linqiutian/workspace/linux/.config
或使用默认配置:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
注意:这些操作需要在内核源代码目录有写权限。

insmod helloDev.ko
[ 1108.216925] helloDev: loading out-of-tree module taints kernel.
[ 1108.225087] Hello: Module loaded successfully! Major number: 511
[ 1108.225324] Hello: Create device file with: mknod /dev/hello_dev c 511 0

. 模块已成功加载,显示”Module loaded successfully”和主设备号511

  1. 内核日志提示需要创建设备文件

  2. 测试步骤需要:

创建设备节点
测试设备访问
验证模块功能
4. 解决方案:

提供完整的设备测试流程
包括读写测试方法
恭喜模块加载成功!以下是完整的测试步骤:

  1. 首先创建设备节点:

sudo mknod /dev/hello_dev c 511 0
sudo chmod 666 /dev/hello_dev

  1. 基本设备文件测试:

ls -l /dev/hello_dev # 应显示crw-rw-rw-权限
file /dev/hello_dev # 应显示字符设备文件

  1. 测试设备读写(根据您的驱动实现):

写入测试

echo “test message” > /dev/hello_dev

读取测试

cat /dev/hello_dev
4. 检查内核日志:

dmesg | tail -n 10

应该能看到驱动处理读写操作的日志

  1. 压力测试(可选):

连续写入测试

for i in {1..10}; do echo “test $i” > /dev/hello_dev; done

连续读取测试

for i in {1..10}; do cat /dev/hello_dev; done
6. 测试完成后清理:

sudo rm /dev/hello_dev
sudo rmmod helloDev

交叉编译

当前已知信息:

目标:编译并加载helloDev.ko内核模块
系统架构:ARM64 (aarch64)
内核版本:5.10.0
模块源代码位置:~/workspace/helloDev/
4. 需要采取的步骤:

清理之前的编译尝试
从基础步骤开始指导
确保每一步都清晰可执行
5. 解决方案:

提供从头开始的完整指导
分步骤验证每个环节当前已知信息:

目标:编译并加载helloDev.ko内核模块
系统架构:ARM64 (aarch64)
内核版本:5.10.0
模块源代码位置:~/workspace/helloDev/
4. 需要采取的步骤:

清理之前的编译尝试
从基础步骤开始指导
确保每一步都清晰可执行
5. 解决方案:

提供从头开始的完整指导
分步骤验证每个环节

  1. 准备工作:

安装交叉编译工具链

sudo apt-get install gcc-aarch64-linux-gnu

进入模块目录

cd ~/workspace/helloDev

清理之前的编译结果

make clean
3. 设置环境变量:

export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
4. 编译模块:

make -C /home/linqiutian/workspace/linux M=$(pwd) modules
5. 验证结果:

检查生成的模块

file helloDev.ko

应该显示”ARM aarch64”架构

加载模块

sudo insmod helloDev.ko

检查是否加载成功

lsmod | grep helloDev
dmesg | tail

首先确保安装了ARM64交叉编译工具链:

1
sudo apt-get install gcc-aarch64-linux-gnu

关键注意事项:

必须使用与运行内核(5.10.0)完全相同的源代码版本
确保内核配置(.config)匹配
编译环境变量设置:

1
2
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

使用正确的架构参数重新编译模块:

1
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -C /home/linqiutian/workspace/linux M=$PWD modules

在qemu中测试字符驱动

1.加载模块到内核:

1
insmod helloDev.ko
  1. 检查模块加载状态:
1
lsmod | grep helloDev
  1. 查看模块初始化输出:
1
dmesg | tail -n 10
  1. 卸载模块:
1
sudo rmmod helloDev

检查模块退出输出:

1
dmesg | tail -n 10

首先创建设备节点:

1
2
mknod /dev/hello_dev c 511 0
chmod 666 /dev/hello_dev

基本设备文件测试:

1
2
ls -l /dev/hello_dev  # 应显示crw-rw-rw-权限
file /dev/hello_dev # 应显示字符设备文件

测试设备读写(根据您的驱动实现):

1
2
3
4
# 写入测试
echo "test message" > /dev/hello_dev
# 读取测试
cat /dev/hello_dev

检查内核日志:

1
dmesg | tail -n 10

测试完成后清理:

1
2
rm /dev/hello_dev
rmmod helloDev

运行测试程序

首先在主机上交叉编译test.c

1
2
3
aarch64-linux-gnu-gcc -static -o test test.c
file test # 确认输出为ARM aarch64架构

将编译好的程序传输到QEMU中:

1
sudo cp test /qemu_shared/
1
2
3
4
5
6
7
8
9
./test
[ 627.996160] Hello: Device opened
[ 627.996437] Hello: Received 22 characters from the user: Hello from user space!
Wrote to device: Hello from user space!
[ 628.001305] Hello: Sent 22 characters to the user
Read from device: Hello from user space!
Data verification successful
[ 628.002348] Hello: Device closed

测试程序test已成功运行,并与内核模块helloDev交互

  1. 从内核日志可见完整的设备操作流程:

设备打开
用户空间写入数据
驱动接收并回传数据
设备关闭
3. 测试结果显示:

写入和读取操作都成功完成
数据验证通过,表明驱动功能正常
4. 结论:

驱动模块helloDev.ko工作正常
测试程序test验证了驱动的完整功能
测试结果分析:

✅ 驱动模块功能验证成功:

  1. 设备操作流程完整:

打开设备 (open)
写入数据 (write)
读取数据 (read)
关闭设备 (close)
2. 数据流验证:

用户空间写入: “Hello from user space!”
驱动正确接收: 22字符
驱动正确回传相同数据
用户空间成功读取并验证数据

  1. 内核日志显示:

[ 627.996160] Hello: Device opened
[ 627.996437] Hello: Received 22 chars
[ 628.001305] Hello: Sent 22 chars
[ 628.002348] Hello: Device closed
4. 用户空间输出:

Wrote to device: Hello from user space!
Read from device: Hello from user space!
Data verification successful

在Ubuntu20.04虚拟机中加载(insmod)字符设备驱动,并⽤运⾏⽤⼾测试程序进⾏测试

先执行清理 重新编译

1
make clean && make all

加载模块:sudo insmod helloDev.ko

1
sudo insmod helloDev.ko

创建设备节点:sudo mknod /dev/hello_dev c [major] 0 (major号会在加载时打印)

从dmesg输出可以看到内核模块已成功加载,主设备号为237

模块期望用户手动创建设备节点:mknod /dev/hello_dev c 237 0

1
sudo mknod /dev/hello_dev c 237 0

设置适当的权限

1
sudo chmod 666 /dev/hello_dev

使用test和write程序测试设备

1
sudo ./test
sudo ./read
open file error
: No such file or directory
linqiutian@ubuntu:~/workspace/hello$ sudo ./write
open file error
No such file or directory
1
sudo mknod /dev/hello c 237 0 && sudo chmod 666 /dev/hello

helloDev - Linux字符设备驱动模块

项目概述

这是一个简单的Linux字符设备驱动模块,实现了基本的设备操作接口(open, read, write, close)。主要用于学习和演示Linux设备驱动开发。

主要文件

  • helloDev.c: 主驱动代码,实现设备操作
  • Makefile: 构建脚本
  • test.c: 综合测试程序
  • read.c: 读取设备示例
  • write.c: 写入设备示例

构建和安装

  1. 确保已安装Linux内核头文件
  2. 执行构建命令:
    1
    make
  3. 加载内核模块:
    1
    sudo insmod helloDev.ko
  4. 创建设备节点:
    1
    2
    sudo mknod /dev/hello c 250 0
    sudo chmod 666 /dev/hello
    (注意: 主设备号250可能需要根据系统调整)

使用示例

写入数据

1
2
gcc write.c -o write
./write

读取数据

1
2
gcc read.c -o read
./read

综合测试

1
2
gcc test.c -o test
./test

卸载模块

1
2
sudo rmmod helloDev
sudo rm /dev/hello

注意事项

  1. 需要root权限加载/卸载模块
  2. 确保主设备号不与系统其他设备冲突
  3. 测试程序可能需要根据实际系统调整