字符设备驱动模板

本文详细描述了一个Linux字符设备驱动程序,包括c_dev结构体定义、read/write数据传输函数、open/release设备操作以及init/exit初始化和卸载函数,展示了如何创建和管理一个自定义设备.
摘要由CSDN通过智能技术生成

c_dev结构体

struct my_device_data {
    // 自定义设备数据结构
    char buffer[BUFFER_SIZE];
    int size;
    struct cdev cdev;
};

read函数

static ssize_t my_device_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
    struct my_device_data *dev_data = file->private_data;
    ssize_t bytes_read = 0;

    // 从设备的缓冲区中读取数据
    if (*offset < dev_data->size) {
        bytes_read = min(count, (size_t)(dev_data->size - *offset));
        if (copy_to_user(buf, dev_data->buffer + *offset, bytes_read)) {
            return -EFAULT;
        }
        *offset += bytes_read;
        printk(KERN_INFO "Read %zd bytes from device\n", bytes_read);
    }

    return bytes_read;
}

write函数

static ssize_t my_device_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
    struct my_device_data *dev_data = file->private_data;
    ssize_t bytes_written = 0;

    // 将数据写入设备的缓冲区
    if (*offset < BUFFER_SIZE) {
        bytes_written = min(count, (size_t)(BUFFER_SIZE - *offset));
        if (copy_from_user(dev_data->buffer + *offset, buf, bytes_written)) {
            return -EFAULT;
        }
        *offset += bytes_written;
        dev_data->size = *offset;
        printk(KERN_INFO "Write %zd bytes to device\n", bytes_written);
    }

    return bytes_written;
}

open函数

static int my_device_open(struct inode *inode, struct file *file)
{
    struct my_device_data *dev_data;

    // 使用 container_of 宏获取设备数据结构体指针
    dev_data = container_of(inode->i_cdev, struct my_device_data, cdev);

    printk(KERN_INFO "Device %s opened\n", DEVICE_NAME);

    // 保存设备数据结构体指针到文件的私有数据指针中
    file->private_data = dev_data;

    return 0;
}

release函数

static int my_device_release(struct inode *inode, struct file *file)
{
    // 在 release 函数中进行资源释放等操作
    printk(KERN_INFO "Device %s released\n", DEVICE_NAME);
    return 0;
}

init函数

static int __init my_device_init(void)
{
    int result;
    my_device = kmalloc(sizeof(struct my_device_data), GFP_KERNEL);
    if (!my_device) {
        return -ENOMEM;
    }
    memset(my_device, 0, sizeof(struct my_device_data));
    my_device->size = 0;

    // 以静态方式请求设备号
    device_numbers = MKDEV(0, 0);
    result = alloc_chrdev_region(&device_numbers, 0, 1, DEVICE_NAME);
    if (result < 0) {
        kfree(my_device);
        return result;
    }
    
    // 将字符设备添加到系统
    cdev_init(&my_device->cdev, &my_device_fops);
    my_device->cdev.owner = THIS_MODULE;

    result = cdev_add(&my_device->cdev, device_numbers, 1);
    if (result < 0) {
        unregister_chrdev_region(device_numbers, 1);
        kfree(my_device);
        return result;
    }

    // 创建设备类
    my_device_class = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(my_device_class)) {
        cdev_del(&my_device->cdev);
        unregister_chrdev_region(device_numbers, 1);
        kfree(my_device);
        return PTR_ERR(my_device_class);
    }

    // 创建设备节点
    device_create(my_device_class, NULL, device_numbers, NULL, DEVICE_NAME);

    return 0;
}

exit函数

static void __exit my_device_exit(void)
{
    cdev_del(&my_device->cdev);
    unregister_chrdev_region(device_numbers, 1);
    device_destroy(my_device_class, device_numbers);
    class_destroy(my_device_class);
    kfree(my_device);
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值