Qemu虚拟arm开发板驱动开发详解(一)——驱动基本架构

这篇具有很好参考价值的文章主要介绍了Qemu虚拟arm开发板驱动开发详解(一)——驱动基本架构。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        此前在《WSL2下Ubuntu22.04使用Qemu搭建虚拟Vexpress-A9开发板》系列文章中,我们已建立好Linux最小系统的运行环境,并将其成功移植到了由Qemu模拟的arm32开发板上。接下来将介绍如何基于上述环境进行驱动开发。

        本节主要带各位读者了解Linux内核驱动的基本架构,并在WSL的Ubuntu22.04子系统下实现基于x86操作系统的简易Linux驱动“HelloWorld”。

Linux驱动框架

#include <linux/module.h> //包含内核编程最常用的函数声明,如printk
#include <linux/kernel.h> //包含模块编程相关的宏定义,如:MODULE_LICENSE

/*init初始化函数在模块被插入进内核时调用,主要作用为驱动功能做好预备工作
  被称为模块的入口函数
  
  __init的作用 : 
1. 一个宏,展开后为:__attribute__ ((__section__ (".init.text")))   实际是gcc的一个特殊链接标记
2. 指示链接器将该函数放置在 .init.text区段
3. 在模块插入时方便内核从ko文件指定位置读取入口函数的指令到特定内存位置
*/
int __init mydriver_init(void)
{
	……………………
	return 0;
}

/*exit退出函数在模块从内核中被移除时调用,主要作用做些init函数的反操作
  被称为模块的出口函数
  
  __exit的作用:
1.一个宏,展开后为:__attribute__ ((__section__ (".exit.text")))   实际也是gcc的一个特殊链接标记
2.指示链接器将该函数放置在 .exit.text区段
3.在模块插入时方便内核从ko文件指定位置读取出口函数的指令到另一个特定内存位置
*/
void __exit mydriver_exit(void)
{
	……………………
}

/*
MODULE_LICENSE(字符串常量);
字符串常量内容为源码的许可证协议 可以是"GPL" "GPL v2"  "GPL and additional rights"  "Dual BSD/GPL"  "Dual MIT/GPL" "Dual MPL/GPL"等, "GPL"最常用

其本质也是一个宏,宏体也是一个特殊链接标记,指示链接器在ko文件指定位置说明本模块源码遵循的许可证
在模块插入到内核时,内核会检查新模块的许可证是不是也遵循GPL协议,如果发现不遵循GPL,则在插入模块时打印抱怨信息:
	myhello:module license 'unspecified' taints kernel
	Disabling lock debugging due to kernel taint
也会导致新模块没法使用一些内核其它模块提供的高级功能
*/
MODULE_LICENSE("GPL");

/*
module_init 宏
1. 用法:module_init(模块入口函数名) 
2. 动态加载模块,对应函数被调用
3. 静态加载模块,内核启动过程中对应函数被调用
4. 对于静态加载的模块其本质是定义一个全局函数指针,并将其赋值为指定函数,链接时将地址放到特殊区段(.initcall段),方便系统初始化统一调用。
5. 对于动态加载的模块,由于内核模块的默认入口函数名是init_module,用该宏可以给对应模块入口函数起别名
*/
module_init(mydriver_init);

/*
module_exit宏
1.用法:module_exit(模块出口函数名)
2.动态加载的模块在卸载时,对应函数被调用
3.静态加载的模块可以认为在系统退出时,对应函数被调用,实际上对应函数被忽略
4.对于静态加载的模块其本质是定义一个全局函数指针,并将其赋值为指定函数,链接时将地址放到特殊区段(.exitcall段),方便系统必要时统一调用,实际上该宏在静态加载时没有意义,因为静态编译的驱动无法卸载。
5.对于动态加载的模块,由于内核模块的默认出口函数名是cleanup_module,用该宏可以给对应模块出口函数起别名
*/
module_exit(mydriver_exit);

        以上就是Linux操作系统中驱动程序的基本框架,主要包涵三个部分,一个是模块入口部分,另一个是模块出口部分,最后是源码许可证协议声明。驱动程序中只要存在这三个部分,就能被内核所认可,编译通过,且可以加载运行,但仅有这几个模块是不够的,后续章节将详细讲解驱动代码的其他重要组成部分,在本小节先做一个HelloWorld代码并尝试让它跑起来。

Hello World

        进入WorkSpace,并创建一个新的文件夹Drivers,用于存放以后开发的所有驱动代码,同时所有代码共享同一个Makefile。

makedir -p /home/workspace/drivers
cd /home/workspace/drivers
vim myhello.c

在myhello.c驱动文件中填入以下内容:

/*
    /home/workspace/drivers/myhello.c
*/

#include <linux/module.h>
#include <linux/kernel.h>

int __init myhello_init(void)
{
	printk("##############################################\n");
	printk("##############################################\n");
	printk("##############################################\n");
	printk("################ Hello World! ################\n");
	printk("##############################################\n");
	printk("##############################################\n");
	printk("##############################################\n");
	return 0;
}

void __exit myhello_exit(void)
{
	printk("myhello will exit\n");
}

MODULE_LICENSE("GPL");

module_init(myhello_init);
module_exit(myhello_exit);

接下来新建一个Makefile:

vim Makefile

在Makefile文件中输入以下内容:

ifeq ($(KERNELRELEASE),)

ifeq ($(ARCH),arm)
KERNELDIR ?= /home/workspace/linux-5.10.186
OBJECTDIR ?= /home/workspace/objects/vexpress-v2p-ca9
ROOTFS ?= /sync/rootfs
CROSS_COMPILE ?= arm-linux-gnueabi-
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
endif
PWD := $(shell pwd)

modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) CROSS_COMPILE=$(CROSS_COMPILE) O=$(OBJECTDIR) modules

modules_install:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) CROSS_COMPILE=$(CROSS_COMPILE) O=$(OBJECTDIR) modules INSTALL_MOD_PATH=$(ROOTFS) modules_install

clean:
	rm -rf  *.o  *.ko  .*.cmd  *.mod*  modules.order  Module.symvers   .tmp_versions

else
	obj-m += myhello.o

endif

宿主机运行环境搭建

        如果是完整的Ubuntu操作系统,则可以省掉这个步骤,直接对上述代码进行make操作,编译驱动代码。但如果Ubuntu操作系统不完整,或者是属于WSL这种微软特供版子系统,则需要进行其他操作,才能确保驱动编译过程中不会出现环境问题。

首先查看操作系统内核版本:

uname -r

qemu-arm,QEMU搭建ARM虚拟开发板,嵌入式Linux开发,Linux内核驱动开发,驱动开发,linux,ubuntu

如果是WSL子系统,则显示结果和上图差不多,如果不是微软特供版的内核,则可以输入以下命令查看内核编译环境是否完整:

ls /lib/modules/$(uname -r)

如果显示文件夹下存在build、kernel、source三个子文件夹,则说明内核编译环境基本完整,可以尝试对驱动代码进行编译,如果以上命令提示文件夹不存在之类的情况,则尝试按照下列步骤进行操作。

通用内核

        如果输入uname -r显示的不是微软特供版,而是类似于4.15.0-162-generic之类的格式,则说明操作系统采用的是Linux通用内核,输入以下指令可以直接安装编译环境。

sudo apt install linux-headers-$(uname -r)

WSL内核

        如果输入uname -r显示的是类似5.15.90.1-microsoft-standard-WSL2的格式,则说明操作系统采用的是微软特供版内核,需要下载源码单独进行编译安装。

        进入 Releases · microsoft/WSL2-Linux-Kernel · GitHub 网站上下载对应uname -r显示的内核源码,然后执行下述步骤。

安装依赖

sudo apt install libelf-dev build-essential pkg-config bison build-essential flex libssl-dev libelf-dev bc dwarves

将内核源码拷贝到workspace(其中,/.../为源码下载到本地的路径)

sudo cp /.../WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz /home/workspace

进入workspace并解压

cd /home/workspace
tar -xvf WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1.tar.gz

进入源码目录并编译安装

cd WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1
cp Microsoft/config-wsl .config

执行以下指令进行编译安装

sudo make scripts
sudo make modules -j$(nproc)
sudo make modules_install

安装成功后提示如下图所示

qemu-arm,QEMU搭建ARM虚拟开发板,嵌入式Linux开发,Linux内核驱动开发,驱动开发,linux,ubuntu

其中有个错误no binutils support,忽略即可,目前不需要直接编译x86架构的32位程序。

编译加载x86架构驱动

编译驱动

cd /home/workspace/drivers
sudo make

qemu-arm,QEMU搭建ARM虚拟开发板,嵌入式Linux开发,Linux内核驱动开发,驱动开发,linux,ubuntu

加载驱动

sudo insmod myhello.ko

任意终端输入dmesg查看内核打印信息: 

qemu-arm,QEMU搭建ARM虚拟开发板,嵌入式Linux开发,Linux内核驱动开发,驱动开发,linux,ubuntu

 移除驱动

sudo rmmod myhello

任意终端输入dmesg查看内核打印信息: 

qemu-arm,QEMU搭建ARM虚拟开发板,嵌入式Linux开发,Linux内核驱动开发,驱动开发,linux,ubuntu

        可以注意到,加载内核的过程中出现loading out-of-tree module taints kernel.提示,意思是加载的树外模块污染了内核。这是我们没有把此驱动模块加入到Kconfig树导致的,即make menuconfig的配置选项中没有此驱动,此时这个驱动模块仍能正常加载和使用。如果仅仅用于学习和验证驱动,则可以忽略此提示,但如果是要求正式写入操作系统的驱动,则需要在Kconfig树中加入驱动信息,这样操作可以直接在menuconfig中选择是否加载驱动,同时也不会出现loading out-of-tree module taints kernel.提示了。

        下一节将介绍如何在Linux内核源码内添加驱动,并在操作系统启动时静态加载驱动代码。文章来源地址https://www.toymoban.com/news/detail-755521.html

到了这里,关于Qemu虚拟arm开发板驱动开发详解(一)——驱动基本架构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • windows-x86使用qemu打开x86和arm虚拟机

     下载固件(UEFI固件镜像文件,BIOS的替代方案) ) 使用cmd执行qemu命令,配置好环境变量比较方便 准备好一个x86的镜像或者arm的镜像,格式可以为qcow2 打开cmd,执行命令 x86 arm 注:上面字段含义  -m 8192 : 分配8GB内存  -cpu cortex-a72 : 虚拟CPU为ARM Cortex-A72 -smp 8,sockets=4,cores=2 : 虚

    2024年02月16日
    浏览(33)
  • 使用QEMU(x86)模拟运行ARM64架构并进行内核调试

    在 x86 上使用 QEMU 虚拟机模拟并调试 ARM64。 参考:ubuntu虚拟机中使用QEMU搭建ARM64环境 主机 ubuntu 20.04, Linux 5.16.0 QEMU emulator version 7.2.92 (v8.0.0-rc2-23-gefcd0ec14b) :qemu-7.2.29 合适的ARM64内核源码:linux-4.14.221.tar.gz 安装交叉编译工具: sudo apt-get install gcc-aarch64-linux-gnu 命令安装以及源码

    2024年02月09日
    浏览(43)
  • Windows11 上使用 QEMU 创建 Ubuntu aarch64(ARM64)虚拟机

    最近在实现一个混沌测试工具,对汽车上分布式系统执行测试。计划运行在 Linux aarch64 环境,需要确定在目标环境能不能运行,但自己和实验室的电脑都是 x86_64,所以打算建一个虚拟机。 通过 Docker容器或VMware都不支持在 x86_64 宿主机运行 aarch64 容器/虚拟机, Virtual Box 似乎也

    2024年02月03日
    浏览(36)
  • ubuntu22.04 x86环境上使用QEMU搭建arm虚拟机

    apt-get -y install qemu apt-get -y install bridge-utils apt-get -y install vnc4server apt-get -y install qemu-kvm apt install -y qemu-system-arm apt-get -y install libvirt0 apt-get -y install libvirt-daemon apt-get -y install libvirt-daemon-system 安装完成后检查: virsh version ls /usr/bin/|grep qemu wget http://releases.linaro.org/components/kernel/

    2024年02月07日
    浏览(64)
  • qemu+kvm安装银河麒麟V10SP1 arm64 虚拟机

    系统镜像 Kylin-Desktop-V10-SP1-Release-2107-arm64.iso QEMU_EFI.fd(下载地址 http://releases.linaro.org/components/kernel/uefi-linaro/16.02/release/qemu64/QEMU_EFI.fd) 注:麒麟系统要求磁盘大小在50G以上. 参数说明: -m 4096 指定内存大小,单位MB -cpu cortex-a72 CPU 型号 -smp 8,cores=8,threads=1,sockets=1 1颗CPU,8核8线

    2024年01月21日
    浏览(88)
  • QEMU学习(二):LED设备仿真及驱动开发

    在仿真led之前,先来了解一下QEMU源码结构及GPIO仿真原理。 QEMU源码目录 我们只罗列出涉及的少许文件,由此可以看出,我们要仿真的设备文件都放在hw目录下,一般来说一个.c 文件会有一个.h 文件,它们的目录类似。 比如 hw/gpio/imx_gpio.c 对应的头文件为 include/hw/gpio/imx_gpio.

    2024年02月09日
    浏览(40)
  • QEMU学习(六):SPI设备仿真及驱动开发

            SPI和I2C一样也是很常用的串行通信协议,并且框架都很类似,都分主机控制器驱动和设备驱动,主机控制器也就是SOC的SPI控制器接口,一般linux内核都自带主机控制器,我们要做的就是SPI设备驱动。 下面是QEMU自带的SPI模拟程序,位于qemuhwssiimx_spi.c,可以看到当我

    2024年01月24日
    浏览(89)
  • QEMU学习(五):I2C设备仿真及驱动开发

            I2C 是很常用的一个串行通信接口,用于连接各种外设、传感器等器件, 本章我们来学习一下如何在QEMU里仿真I2C设备及 Linux 下开发 I2C 接口器件驱动。 下面是标准的设备添加结构,我们使用的是常见的at_24c系列设备来做I2C的通信,详细代码请看qemuhwnvrameeprom_

    2024年02月08日
    浏览(74)
  • ARM架构基本理论(1)

    ARM (Advanced RISC Machine)是一种基于 RISC(Reduced Instruction Set Computing) 架构的计算机处理器架构,由ARM Holdings(ARM公司)开发和授权给其他公司生产和销售。 ARM架构最初是为低功耗、高效能的嵌入式系统设计的,如智能手机、平板电脑、数字电视、路由器、音频设备、控制器

    2024年02月02日
    浏览(29)
  • windows平台部署arm架构的虚拟机(实测截图)

    平台 windows 由于我近期有一个比赛,而我的主机又是x86架构的,人家要求使用arm架构的主机,我这穷屌丝,不可 能去买一台吧,而且随着国产系统的推进,采用arm架构的主机也越来越多,作为运维我们该怎么利用x86 来运行arm架构的主机成为了一个问题 以下软件版本皆为实验

    2023年04月21日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包