common-android15-6.6 kernel环境下,编写并编译一个helloworld驱动模块

https://blog.csdn.net/Railshiqian/article/details/160374693?spm=1011.2124.3001.6209

本章的目的,是编写一个helloworld驱动模块,此驱动模块会初始化一个/dev/hello_char驱动节点,提供文件读写能力,并编译出android系统可以加载的helloworld.ko文件。

1,准备helloworld源码

cd kernel工程/common-modules/virtual-device

创建helloworld文件夹和helloworld.c文件

bash 复制代码
mkdir helloworld
cd helloworld
touch helloworld.c

helloworld.c里的内容如下:

c 复制代码
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "hello_char"
#define CLASS_NAME  "hello_class"
#define BUF_SIZE    128

static dev_t dev_num;
static struct cdev hello_cdev;
static struct class *hello_class;

static char kernel_buf[BUF_SIZE];
static size_t data_len;

/* open */
static int hello_open(struct inode *inode, struct file *file)
{
    pr_info("hello_char: device opened\n");
    return 0;
}

/* read */
static ssize_t hello_read(struct file *file,
                          char __user *buf,
                          size_t count,
                          loff_t *ppos)
{
    if (*ppos >= data_len)
        return 0;

    if (count > data_len - *ppos)
        count = data_len - *ppos;

    if (copy_to_user(buf, kernel_buf + *ppos, count))
        return -EFAULT;

    *ppos += count;
    return count;
}

/* write */
static ssize_t hello_write(struct file *file,
                           const char __user *buf,
                           size_t count,
                           loff_t *ppos)
{
    if (count > BUF_SIZE)
        count = BUF_SIZE;

    if (copy_from_user(kernel_buf, buf, count))
        return -EFAULT;

    data_len = count;
    pr_info("hello_char: write %zu bytes: %.*s\n",
            count, (int)count, kernel_buf);

    return count;
}

/* file operations */
static const struct file_operations hello_fops = {
    .owner = THIS_MODULE,
    .open  = hello_open,
    .read  = hello_read,
    .write = hello_write,
};

static int __init hello_init(void)
{
    int ret;

    /* 1. alloc major/minor */
    ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME);
    if (ret)
        return ret;

    /* 2. init cdev */
    cdev_init(&hello_cdev, &hello_fops);
    ret = cdev_add(&hello_cdev, dev_num, 1);
    if (ret)
        goto err_cdev;

    /* 3. create class */
    hello_class = class_create(CLASS_NAME);
    if (IS_ERR(hello_class)) {
        ret = PTR_ERR(hello_class);
        goto err_class;
    }

    /* 4. create device node: /dev/hello_char */
    device_create(hello_class, NULL,
                  dev_num, NULL, DEVICE_NAME);

    pr_info("hello_char: init success\n");
    return 0;

err_class:
    cdev_del(&hello_cdev);
err_cdev:
    unregister_chrdev_region(dev_num, 1);
    return ret;
}

static void __exit hello_exit(void)
{
    device_destroy(hello_class, dev_num);
    class_destroy(hello_class);
    cdev_del(&hello_cdev);
    unregister_chrdev_region(dev_num, 1);

    pr_info("hello_char: exit\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Example");
MODULE_DESCRIPTION("Android Kernel Char Device Example");

2,配置helloworld模块编译

修改kernel工程/common-modules/virtual-device/BUILD.bazel文件,进行以下修改:

bash 复制代码
diff --git a/BUILD.bazel b/BUILD.bazel
index 2deb1f7..8455d4f 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -79,6 +79,13 @@ filegroup(
     ],
 )
 
+filegroup(
+    name = "helloworld_sources",
+    srcs = [
+        "helloworld/helloworld.c",
+    ],
+)
+
 filegroup(
     name = "vkms_sources",
     srcs = [
@@ -250,6 +257,14 @@ ddk_module(
     deps = [":common_headers_x86_64"],
 )
 
+ddk_module(
+    name = "x86_64/helloworld",
+    srcs = [":helloworld_sources"],
+    out = "helloworld.ko",
+    kernel_build = ":virtual_device_x86_64",
+    deps = [":common_headers_x86_64"],
+)
+
 ddk_module(
     name = "x86_64/vkms",
     srcs = [":vkms_sources"],
@@ -265,6 +280,7 @@ kernel_module_group(
         ":x86_64/goldfish_drivers/goldfish_pipe",
         ":x86_64/goldfish_drivers/goldfish_sync",
         ":x86_64/v4l2loopback",
+        ":x86_64/helloworld",
         ":x86_64/vkms",
         "//common-modules/virtio-media/driver:x86_64/virtio-media",
     ],

3,编译出helloworld.ko文件

用上一章节同样的编译命令,进行重新编译,就可以得到helloworld.ko:

在kernel工程根目录下,执行编译命令:

bash 复制代码
tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist --distdir=out

输出:

bash 复制代码
......
[dist] DEBUG: Copying file: out/virtual_device_x86_64/dist/helloworld.ko
......

4,将ko文件推到模拟器设备里进行加载和卸载,以及文件调试

bash 复制代码
推ko文件到设备:adb push out/virtual_device_x86_64/dist/helloworld.ko /data/

进android shell环境:adb shell

通过insmod 命令加载ko模块:insmod /data/helloworld.ko

确认helloworld模块已初始化:
adb logcat -b all |tee ~/temp.log |grep -Ei "hello"
04-21 15:23:01.383     0     0 I hello_char: exit
04-21 15:23:12.901     0     0 I hello_char: init success

确认/dev/hello_char驱动文件节点已创建:
emulator_car64_x86_64:/ # file /dev/hello_char                                                                                                                                                                                             
/dev/hello_char: character special (504/0)

对文件进行写 + 读:
emulator_car64_x86_64:/ # echo hello > /dev/hello_char

emulator_car64_x86_64:/ # cat /dev/hello_char
hello
相关推荐
方白羽3 小时前
Android APK安全防护
android·安全·apk
小黄人软件3 小时前
AndroidStudio老项目 macOS运行BlueTooth蓝牙串口助手(Android+Studio源码).rar
android·macos
00后程序员张3 小时前
苹果App Store上架指南:费用、原理与步骤详解
android·ios·小程序·https·uni-app·iphone·webview
天神哥哥啊3 小时前
cocos联调注意事项-安卓
android
TDengine (老段)3 小时前
TDengine TSDB 实战排障四(升级与兼容)
android·java·大数据·数据库·物联网·时序数据库·tdengine
蓝速科技4 小时前
政务自助终端信创选型与无人值守落地方案
android·大数据·数据库·人工智能·科技·技术分享·政务
硫酸锌015 小时前
在手机上运行Python增量备份手机数据到PC电脑
android·windows·python
hai_android6 小时前
子 View 被压小时,如何向父容器"告状"?——MEASURED_STATE_TOO_SMALL 向上传递机制
android·kotlin·android jetpack
AFinalStone6 小时前
Android 7 多用户源码解析(七)系统服务的多用户感知处理
android·系统架构·多用户
怪奇云呼军6 小时前
从 ElevenLabs 看工具调用:闪电智能 Voice Agent 的企业集成验收设计
android·大数据·运维·服务器·网络·人工智能·kotlin