字符设备触发中断

字符设备触发中断-未完

示例代码如下

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>

#define DEVICE_NAME "my_device" // 设备名称

static spinlock_t my_lock;
static int shared_data = 0;
static dev_t dev_num;
static struct cdev c_dev;
static struct class *dev_class;
static struct device *dev;

static irqreturn_t my_interrupt_handler(int irq, void *data)
{
    unsigned long flags; // 用于保存中断状态的标志
    spin_lock_irqsave(&my_lock, flags); // 在中断服务函数中获取自旋锁并保存中断状态

    // 执行需要保护的操作
    shared_data++;
    
    spin_unlock_irqrestore(&my_lock, flags); // 释放自旋锁并还原中断状态

    return IRQ_HANDLED;
}

static int my_device_open(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "my_device opened\n");
    return 0;
}

static ssize_t my_device_read(struct file *file, char *buf, size_t count, loff_t *pos)
{
    int len, ret;

    spin_lock_irq(&my_lock); // 在进程上下文中获取自旋锁

    len = snprintf(buf, count, "%d", shared_data); // 将共享数据写入缓冲区

    spin_unlock_irq(&my_lock); // 释放自旋锁

    ret = copy_to_user(buf, buf, len); // 将数据从内核空间拷贝到用户空间
    if (ret) {
        return -EFAULT;
    }

    return len;
}

static ssize_t my_device_write(struct file *file, const char *buf, size_t count, loff_t *pos)
{
    printk(KERN_INFO "my_device write operation not supported\n");
    return -EINVAL;
}

static struct file_operations my_device_fops = {
    .owner = THIS_MODULE,
    .open = my_device_open,
    .read = my_device_read,
    .write = my_device_write,
};

static int __init my_driver_init(void)
{
    int ret;

    spin_lock_init(&my_lock); // 初始化自旋锁

    // 分配字符设备号
    ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME);
    if (ret < 0) {
        printk(KERN_ERR "Failed to allocate device number\n");
        return ret;
    }

    // 初始化字符设备并注册
    cdev_init(&c_dev, &my_device_fops);
    ret = cdev_add(&c_dev, dev_num, 1);
    if (ret < 0) {
        printk(KERN_ERR "Failed to add char device\n");
        unregister_chrdev_region(dev_num, 1);
        return ret;
    }

    // 创建设备类和设备节点
    dev_class = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(dev_class)) {
        printk(KERN_ERR "Failed to create device class\n");
        cdev_del(&c_dev);
        unregister_chrdev_region(dev_num, 1);
        return PTR_ERR(dev_class);
    }
    dev = device_create(dev_class, NULL, dev_num, NULL, DEVICE_NAME);
    if (IS_ERR(dev)) {
        printk(KERN_ERR "Failed to create device\n");
        class_destroy(dev_class);
        cdev_del(&c_dev);
        unregister_chrdev_region(dev_num, 1);
        return PTR_ERR(dev);
    }

    // 请求中断并注册中断处理程序
    if (request_irq(IRQ_NUMBER, my_interrupt_handler, IRQF_SHARED, "my_interrupt", (void*)(my_interrupt_handler))) {
        printk(KERN_ERR "Failed to register interrupt\n");
        device_destroy(dev_class, dev_num);
        class_destroy(dev_class);
        cdev_del(&c_dev);
        unregister_chrdev_region(dev_num, 1);
        return -ENODEV;
    }

    return 0;
}

static void __exit my_driver_exit(void)
{
    // 取消中断处理程序注册,并释放中断
    free_irq(IRQ_NUMBER, (void*)(my_interrupt_handler));

    // 销毁设备类和设备节点
    device_destroy(dev_class, dev_num);
    class_destroy(dev_class);

    // 删除字符设备
    cdev_del(&c_dev);

    // 释放设备号
    unregister_chrdev_region(dev_num, 1);

    spin_lock_destroy(&my_lock); // 销毁自旋锁
}

module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_LICENSE("GPL");
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值