【Linux设备驱动】--0x03字符设备模块-完整的错误处理+全局数据结构放在同一结构体内

简介: 项目中经常会将所用到的所有全局数据结构放到同一个结构体内struct simple_dev { dev_t dev_no; struct cdev cdev; struct class *class; struct device *device;};该...

项目中经常会将所用到的所有全局数据结构放到同一个结构体内

struct simple_dev {
    dev_t  dev_no;
    struct cdev   cdev;
    struct class  *class;
    struct device *device;
};

该结构体将所用到的全局数据结构放在一起,这样可以在open的时候,将该指针放到file->private_data = dev;私有data字段内,方便其他系统调用接口使用

这里container_of无法操作内部嵌套的指针类型,所以struct cdev cdev;不能用作指针类型

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/slab.h>   // kfree,kmalloc
#include <linux/cdev.h>   // cdev_xxx
#include <linux/device.h> // device_xxx

struct simple_dev {
    dev_t  dev_no;
    struct cdev   cdev;
    struct class  *class;
    struct device *device;
};

struct simple_dev *g_simple_dev;

static int simple_cdev_open(struct inode *inode, struct file *file)
{
    struct simple_dev *dev;

    dev = container_of(inode->i_cdev, struct simple_dev, cdev);
    file->private_data = dev;

    return 0;
}

static int simple_cdev_release(struct inode *inode, struct file *file)
{
    struct simple_dev *dev;

    dev = file->private_data;

    return 0;
}

/* File operations struct for character device */
static const struct file_operations g_simple_dev_fops = {
    .owner   = THIS_MODULE,
    .open    = simple_cdev_open,
    .release = simple_cdev_release,
};

static int __init simple_cdev_init(void)
{
    int ret;

    g_simple_dev = kzalloc(sizeof(struct simple_dev), GFP_KERNEL);
    if (!g_simple_dev) {
        return -1;
    }

    ret = alloc_chrdev_region(&g_simple_dev->dev_no, 0, 1, "simple_cdev");
    if (!ret) {
        goto alloc_chrdev_failed;
    }

    cdev_init(&g_simple_dev->cdev, &g_simple_dev_fops);
    g_simple_dev->cdev.owner = THIS_MODULE;

    ret = cdev_add(&g_simple_dev->cdev, g_simple_dev->dev_no, 1);
    if (!ret) {
        goto cdev_add_failed;
    }

    g_simple_dev->class = class_create(THIS_MODULE, "simple_cdev");
    if (!g_simple_dev->class) {
        goto class_create_failed;
    }

    g_simple_dev->device = device_create(g_simple_dev->class, NULL, g_simple_dev->dev_no, NULL, "simple_cdev");
    if (!g_simple_dev->device) {
        goto device_create_failed;
    }
    
    return 0;

device_create_failed:
    class_destroy(g_simple_dev->class);
class_create_failed:
    cdev_del(&g_simple_dev->cdev);
cdev_add_failed:
    unregister_chrdev_region(g_simple_dev->dev_no, 1);
alloc_chrdev_failed:
    kfree(g_simple_dev);

    return -1;
}

static void __exit simple_cdev_exit(void)
{
    device_destroy(g_simple_dev->class, g_simple_dev->dev_no);
    class_destroy(g_simple_dev->class);
    cdev_del(&g_simple_dev->cdev);
    unregister_chrdev_region(g_simple_dev->dev_no, 1);
    kfree(g_simple_dev);
}

MODULE_LICENSE("GPL");
module_init(simple_cdev_init);
module_exit(simple_cdev_exit);
目录
相关文章
|
2月前
|
测试技术 Linux
Linux(8)Debain系统测试EC25-EUX模块usbnet0(qmi qcm)问题点
Linux(8)Debain系统测试EC25-EUX模块usbnet0(qmi qcm)问题点
91 0
|
2月前
|
存储 Linux C语言
Linux:冯·诺依曼结构 & OS管理机制
Linux:冯·诺依曼结构 & OS管理机制
39 0
|
3天前
|
SQL 自然语言处理 网络协议
【Linux开发实战指南】基于TCP、进程数据结构与SQL数据库:构建在线云词典系统(含注册、登录、查询、历史记录管理功能及源码分享)
TCP(Transmission Control Protocol)连接是互联网上最常用的一种面向连接、可靠的、基于字节流的传输层通信协议。建立TCP连接需要经过著名的“三次握手”过程: 1. SYN(同步序列编号):客户端发送一个SYN包给服务器,并进入SYN_SEND状态,等待服务器确认。 2. SYN-ACK:服务器收到SYN包后,回应一个SYN-ACK(SYN+ACKnowledgment)包,告诉客户端其接收到了请求,并同意建立连接,此时服务器进入SYN_RECV状态。 3. ACK(确认字符):客户端收到服务器的SYN-ACK包后,发送一个ACK包给服务器,确认收到了服务器的确
|
14天前
|
存储 安全 Linux
深入解析Linux命令p11-kit:PKCS#11模块的协调器
**p11-kit详解:连接PKCS#11模块的桥梁** p11-kit是Linux下管理PKCS#11加密设备的库,它提供统一接口,简化与智能卡、HSM等的交互。用于密码学开发、系统集成及云服务,支持动态加载模块,通过API简化编程。安装时注意依赖,选择合适方式,关注版本兼容性,并通过文档和测试确保稳定。代码示例展示如何加载和卸载PKCS#11模块。
|
20天前
|
安全 Linux 数据处理
探索Linux的kmod命令:管理内核模块的利器
`kmod`是Linux下管理内核模块的工具,用于加载、卸载和管理模块及其依赖。使用`kmod load`来加载模块,`kmod remove`卸载模块,`kmod list`查看已加载模块,`kmod alias`显示模块别名。注意需有root权限,且要考虑依赖关系和版本兼容性。最佳实践包括备份、查阅文档和使用额外的管理工具。
|
5天前
|
运维 Linux 应用服务中间件
Linux之自动化运维工具ansible、ansible模块(2)
Linux之自动化运维工具ansible、ansible模块(2)
|
5天前
|
运维 Linux Shell
Linux之自动化运维工具ansible、ansible模块(1)
Linux之自动化运维工具ansible、ansible模块(1)
|
2月前
|
Linux
探索Linux操作系统的内核模块
本文将深入探讨Linux操作系统的核心组成部分——内核模块,揭示其背后的工作机制和实现方式。我们将从内核模块的定义开始,逐步解析其加载、卸载以及与操作系统其他部分的交互过程,最后探讨内核模块在系统性能优化中的关键作用。
|
2月前
|
存储 安全 Unix
2023年最详细介绍Linux 系统目录结构!你确定不来了解一下吗?
2023年最详细介绍Linux 系统目录结构!你确定不来了解一下吗?
|
2月前
|
存储 网络协议 Linux
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(下)
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(下)