1. 初始化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 # 查看内核日志
验证方法
通过以下步骤确认初始化成功:
- 模块加载:
lsmod | grep camera_core应显示模块已加载。 - 设备节点:
ls -l /dev/camera_dev应存在字符设备节点。 - 内核日志:
dmesg应输出Camera core: device camera_dev created (type=0, ops=0x1f),其中type=0表示传感器类型,ops=0x1f表示支持全部5种操作。 - 卸载清理:
sudo rmmod camera_core后,/dev/camera_dev消失,dmesg显示卸载日志。
通过条件:上述4项全部满足,且无内核错误(dmesg无BUG/ERROR字样),即判定本案例实现正确。