1. 初始化Camera子系统核心数据结构

初始化Camera子系统核心数据结构 学习卡片

任务说明

本案例实现Linux内核Camera子系统中最基础的数据结构struct camera_device的创建与初始化。该结构体是Camera设备在内核中的核心抽象,后续所有Camera操作(打开、关闭、流控制等)均基于此结构体展开。完成本案例后,你将得到一个可编译、可加载的内核模块,它能够正确初始化一个Camera设备实例并注册到内核中。

环境依赖

  • Linux内核源码树(本案例基于5.10+版本,接口兼容4.19+)
  • 内核头文件与编译工具链(gcc、make)
  • 目标平台:x86_64或ARM(本案例代码与架构无关)

核心实现

以下代码定义并初始化struct camera_device。该结构体包含设备类型、支持的操作集合、互斥锁以及引用计数等关键字段。模块加载时执行初始化,卸载时执行清理。

// camera_core.c
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/kref.h>

#define CAMERA_DEVICE_NAME "camera_dev"
#define CAMERA_CLASS_NAME "camera_class"

// Camera设备支持的操作类型
enum camera_device_type {
    CAMERA_TYPE_SENSOR = 0,
    CAMERA_TYPE_ISP,
    CAMERA_TYPE_CONTROLLER,
};

// Camera设备支持的操作标志位
#define CAMERA_OP_OPEN      BIT(0)
#define CAMERA_OP_RELEASE   BIT(1)
#define CAMERA_OP_START     BIT(2)
#define CAMERA_OP_STOP      BIT(3)
#define CAMERA_OP_SET_FMT   BIT(4)

// 核心数据结构
struct camera_device {
    unsigned int index;              // 设备编号
    enum camera_device_type type;    // 设备类型
    unsigned long ops;               // 支持的操作位图
    struct mutex lock;               // 访问保护锁
    struct kref refcount;            // 引用计数
    struct cdev cdev;                // 字符设备
    struct device *dev;              // 内核设备
    void *priv_data;                 // 私有数据指针
};

static dev_t camera_dev_num;
static struct class *camera_class;
static struct camera_device *g_camera;

// 引用计数释放回调
static void camera_device_release(struct kref *kref)
{
    struct camera_device *cam = container_of(kref, struct camera_device, refcount);
    kfree(cam);
}

// 初始化Camera设备核心结构
static struct camera_device *camera_device_create(unsigned int index,
                                                  enum camera_device_type type,
                                                  unsigned long ops)
{
    struct camera_device *cam;

    cam = kzalloc(sizeof(*cam), GFP_KERNEL);
    if (!cam)
        return ERR_PTR(-ENOMEM);

    cam->index = index;
    cam->type = type;
    cam->ops = ops;
    cam->priv_data = NULL;
    mutex_init(&cam->lock);
    kref_init(&cam->refcount);
    cdev_init(&cam->cdev, NULL);  // 实际驱动会绑定file_operations
    cam->cdev.owner = THIS_MODULE;

    return cam;
}

static int __init camera_core_init(void)
{
    int ret;

    // 分配设备号(动态)
    ret = alloc_chrdev_region(&camera_dev_num, 0, 1, CAMERA_DEVICE_NAME);
    if (ret < 0)
        return ret;

    // 创建设备类
    camera_class = class_create(THIS_MODULE, CAMERA_CLASS_NAME);
    if (IS_ERR(camera_class)) {
        ret = PTR_ERR(camera_class);
        goto err_unregister_region;
    }

    // 创建并初始化核心结构体
    g_camera = camera_device_create(0, CAMERA_TYPE_SENSOR,
                                    CAMERA_OP_OPEN | CAMERA_OP_RELEASE |
                                    CAMERA_OP_START | CAMERA_OP_STOP);
    if (IS_ERR(g_camera)) {
        ret = PTR_ERR(g_camera);
        goto err_destroy_class;
    }

    // 将字符设备添加到内核
    ret = cdev_add(&g_camera->cdev, camera_dev_num, 1);
    if (ret < 0)
        goto err_free_camera;

    // 创建设备节点 /dev/camera_dev
    g_camera->dev = device_create(camera_class, NULL, camera_dev_num, NULL,
                                  CAMERA_DEVICE_NAME);
    if (IS_ERR(g_camera->dev)) {
        ret = PTR_ERR(g_camera->dev);
        goto err_cdev_del;
    }

    pr_info("Camera core: device %s created (type=%d, ops=0x%lx)\n",
            CAMERA_DEVICE_NAME, g_camera->type, g_camera->ops);
    return 0;

err_cdev_del:
    cdev_del(&g_camera->cdev);
err_free_camera:
    kfree(g_camera);
err_destroy_class:
    class_destroy(camera_class);
err_unregister_region:
    unregister_chrdev_region(camera_dev_num, 1);
    return ret;
}

static void __exit camera_core_exit(void)
{
    if (!g_camera)
        return;

    device_destroy(camera_class, camera_dev_num);
    cdev_del(&g_camera->cdev);
    kref_put(&g_camera->refcount, camera_device_release);
    class_destroy(camera_class);
    unregister_chrdev_region(camera_dev_num, 1);
    pr_info("Camera core: module unloaded\n");
}

module_init(camera_core_init);
module_exit(camera_core_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Camera core subsystem - device structure init");
MODULE_VERSION("1.0");

编译与加载

创建Makefile(与源码同目录):

obj-m += camera_core.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

执行编译与加载:

make
sudo insmod camera_core.ko
dmesg | tail -5    # 查看内核日志

验证方法

通过以下步骤确认初始化成功:

  1. 模块加载:lsmod | grep camera_core应显示模块已加载。
  2. 设备节点:ls -l /dev/camera_dev应存在字符设备节点。
  3. 内核日志:dmesg应输出Camera core: device camera_dev created (type=0, ops=0x1f),其中type=0表示传感器类型,ops=0x1f表示支持全部5种操作。
  4. 卸载清理:sudo rmmod camera_core后,/dev/camera_dev消失,dmesg显示卸载日志。

通过条件:上述4项全部满足,且无内核错误(dmesg无BUG/ERROR字样),即判定本案例实现正确。