在ubuntu上开发编译内核模块,并查看printk打印的消息

本文介绍了一个简单的Linux内核模块实现,并展示了如何通过C++类进行基本的对象操作。文章包括了模块的源码、Makefile配置及编译指南,同时提供了C++类定义与使用的示例。

模块源码:

// 下面的是主要的内容
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>


MODULE_LICENSE("GPL");


static int year=2017;


int hello_init()
{
    printk(KERN_WARNING "Hello kernel, it's %d!\n",year);
    return 0;
}




void hello_exit()
{
    printk("Bye, kernel!\n");
}


// 下面两个为关键的模块函数
module_init(hello_init);
module_exit(hello_exit);

Makefile:

ifneq ($(KERNELRELEASE),)


obj-m := helloworld.o


else


KDIR=/lib/modules/3.5.0-23-generic/build
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.c *.symvers
endif

执行makefile编译模块-》执行insmod helloworld.ko控制台不会显示printk打印的消息,应该使用 dmesg -c指令。成功看到打印的消息

root@ubuntu:/home/gec/driver# dmesg -c
[706893.639845] Hello kernel, it's 2017!

c++类头文件

#ifndef MAN_H
#define MAN_H


class Man
{
public:
    Man();
    ~Man();
    void eat();
};

#endif // MAN_H

c++类源文件

#include "man.h"
#include <stdio.h>
Man::Man()
{
    printf("man created\n");
}
Man::~Man(){
    printf("man freed\n");
}

void Man::eat(){
    printf("man eat\n");
}
extern "C"{
  void test();
}
void test(){
//    Man *man=new Man();
//    man->eat();
    Man man;
    man.eat();
}

c头文件

#ifndef C_H
#define C_H



extern void test();
void ctest();


#endif // C_H

c源文件

#include "c.h"

void ctest(){
    test();
}

测试入口main.cpp

#include <iostream>
extern "C"{
#include "c.h"
}
using namespace std;

int main(int argc, char *argv[])
{
    cout << "Hello World!" << endl;
    ctest();
    return 0;
}

测试结果:

Hello World!

man created

man eat

man freed

<think>嗯,用户问的是如何在PC端的虚拟机上编译ARM64嵌入式开发板上的内核模块。首先,我需要确定用户的使用场景。可能的情况是,用户正在为ARM64架构的嵌入式设备开发内核模块,但希望在自己的PC上使用虚拟机进行交叉编译,这样可以提高开发效率,而无需直接在目标硬件上进行编译。 接下来,我需要考虑用户可能已经具备的知识。用户可能了解基本的Linux操作和内核模块开发,但对交叉编译的具体步骤可能不太熟悉。可能他们之前尝试过直接在开发板上编译,但发现效率低下,或者他们刚开始接触嵌入式开发,需要指导如何设置交叉编译环境。 用户的需求不仅仅是步骤,可能还包括为什么需要这些步骤,以及如何验证每一步是否正确。例如,为什么需要安装交叉编译工具链,如何配置内核源码等。此外,用户可能遇到常见问题,比如工具链的路径设置不正确,内核版本与目标设备不匹配,或者在传输模块到目标设备后无法加载。 接下来,我需要整理编译ARM64内核模块的步骤。首先,安装交叉编译工具链是关键,因为PC通常是x86架构,而目标设备是ARM64。需要选择合适的工具链,比如Linaro或ARM官方提供的工具链。然后,获取目标设备的内核源码,确保版本与设备上运行的内核一致,否则编译出的模块可能无法加载。配置内核源码可能需要使用设备提供的配置文件,或者从设备中导出的.config文件。 编写Makefile时需要指定ARCH和CROSS_COMPILE变量,指向正确的架构和交叉编译器路径。编译完成后,将生成的.ko文件传输到目标设备,使用insmod或modprobe加载,检查dmesg输出是否有错误。 用户可能遇到的问题包括工具链安装错误、内核源码配置不正确、模块版本不匹配等。需要提醒用户注意这些点,建议在遇到问题时检查工具链路径、内核版本和配置文件。 此外,用户可能需要优化开发流程,比如使用版本控制、自动化脚本或虚拟机的共享文件夹功能。这些建议可以帮助用户提高效率,减少重复劳动。 最后,需要确认用户是否了解如何将模块传输到目标设备,可能使用scp或其他方法,以及在目标设备上加载模块的权限问题,比如是否需要root权限。总结来说,整个流程的关键点在于正确设置交叉编译环境、内核配置和Makefile,确保模块与目标内核兼容。</think>在 PC 端虚拟机上为 ARM64 嵌入式开发编译内核模块,本质是通过 **交叉编译(Cross-Compile)** 实现的。以下是详细步骤和关键注意事项: --- ### **1. 准备工作** #### **(1) 安装交叉编译工具链** - ARM64 开发板的 CPU 架构是 `aarch64`(即 ARM 64 位),需在 x86 PC 上安装对应的交叉编译器: ```bash # Ubuntu/Debian 系统安装官方工具链 sudo apt-get install gcc-aarch64-linux-gnu ``` 验证安装: ```bash aarch64-linux-gnu-gcc --version ``` - 如果开发板厂商提供了定制工具链(如某些嵌入式平台),需从官网下载配置环境变量: ```bash export PATH=$PATH:/path/to/toolchain/bin ``` #### **(2) 获取目标内核源码** - **必须使用与开发板运行的内核完全一致的源码**,否则编译的模块无法加载(版本不匹配)! - 从开发板厂商获取内核源码(或通过 Git 拉取特定版本)。 - 若开发板运行的是标准 Linux 内核,需确认其版本(通过 `uname -r` 在开发板上查看)。 #### **(3) 配置内核源码** - 进入内核源码目录,使用开发板的配置文件(如厂商提供的 `defconfig`): ```bash cd /path/to/kernel-source make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig # 使用默认配置 # 或复制开发板实际使用的 .config 文件到源码目录 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- oldconfig # 根据现有配置更新 ``` --- ### **2. 编写内核模块** 假设模块代码为 `hello_module.c`: ```c #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); static int __init hello_init(void) { printk(KERN_INFO "Hello ARM64 Module!\n"); return 0; } static void __exit hello_exit(void) { printk(KERN_INFO "Goodbye ARM64 Module!\n"); } module_init(hello_init); module_exit(hello_exit); ``` --- ### **3. 编写 Makefile** 创建 `Makefile`,指定交叉编译参数: ```makefile KDIR := /path/to/kernel-source # 内核源码路径 ARCH := arm64 CROSS_COMPILE := aarch64-linux-gnu- obj-m += hello_module.o all: make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules clean: make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) clean ``` --- ### **4. 执行编译** 在模块源码目录执行: ```bash make ``` 成功后会生成 `hello_module.ko` 文件(ARM64 架构的内核模块)。 --- ### **5. 验证与部署** - **将模块传输到开发板**: ```bash scp hello_module.ko user@arm64-device:/tmp/ ``` - **在开发板上加载模块**: ```bash sudo insmod /tmp/hello_module.ko dmesg | tail # 查看输出日志 ``` --- ### **常见问题与解决** 1. **版本不匹配错误** - 错误信息:`Invalid module format` 或 `version magic '...' mismatch` - **原因**:内核源码版本与开发板运行的内核不一致。 - **解决**:确保内核源码版本、配置与开发板完全一致。 2. **交叉工具链未找到** - **错误**:`aarch64-linux-gnu-gcc: command not found` - **解决**:检查工具链安装路径,在 `Makefile` 中显式指定完整路径: ```makefile CROSS_COMPILE := /usr/bin/aarch64-linux-gnu- ``` 3. **内核源码未配置** - **错误**:`Could not prepare headers for compilation` - **解决**:在内核源码目录执行 `make modules_prepare`。 --- ### **优化开发流程** - **使用虚拟机共享文件夹**:将内核源码和模块代码放在共享目录中,避免重复传输。 - **自动化脚本**:编写脚本一键编译传输模块到开发板。 - **QEMU 模拟**:若开发板是通用 ARM64 架构,可用 QEMU 虚拟机提前测试模块。 --- ### **总结** 关键步骤: 1. 安装正确的交叉工具链。 2. 使用与开发板完全一致的内核源码。 3. 通过 `ARCH` 和 `CROSS_COMPILE` 指定交叉编译参数。 4. 验证模块兼容性后部署到设备。 通过这种方式,你可以高效地在 PC 上为 ARM64 设备开发内核模块,而无需在资源有限的嵌入式设备上直接编译
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无v邪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值