Linux内核有什么之块设备驱动有什么第二回 —— 块设备驱动初始化流程 vs 字符设备驱动初始化流程

news2024/12/24 21:35:31

接前一篇文章:Linux内核有什么之块设备驱动有什么第一回 —— 概述及框架

本文内容参考:

34 | 块设备(上):如何建立代理商销售模式?-趣谈Linux操作系统-极客时间

Linux内核——块设备总结_linux do_open-CSDN博客

【Linux驱动】块设备驱动(一)—— 注册块设备_创建块设备-CSDN博客

特此致谢!

上一回起了头,对于块设备进行了概述,并给出了块设备子系统的框架:

本回限闲言少叙,直接开始解析块设备驱动的代码和机制。

块设备驱动的一般流程

要讲块设备的驱动流程,还得先打字符设备驱动那说起,两者对照着更好理解。

字符设备的核心结构为struct cdev,其在include/linux/cdev.h中定义,代码如下:

struct cdev {
	struct kobject kobj;
	struct module *owner;
	const struct file_operations *ops;
	struct list_head list;
	dev_t dev;
	unsigned int count;
} __randomize_layout;

字符设备驱动的一般初始化流程如下:

(0)加载设备驱动

static int __init xxx_init(void)
{
    ……
}

module_init(xxx_init);

注:下边代码凡是带缩进的,都是在xxx_init()中的。

(1)构建设备号

    dev_t xxx_dev_no = MKDEV(xxx_major, 0);

(2)初始化并准备file_operations结构中的成员

ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    ……
    copy_to_user(buf, ……, ……);
    ……
}

ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    ……
    copy_from_user(……, buf, ……);
    ……
}

long xxx_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    ……
    switch (cmd) {
        case XXX_CMD1:
            ……
            break;
        case XXX_CMD2:
            ……
            break;
        default:
            return -ENOTTY;
    }

    return 0;
}

static int xxx_open(struct inode *inode, struct file *filp)
{
    filp->private_data = ……;
    ……
}

static void xxx_release(struct inode *inode, struct file *filp)
{
    return 0;
}

struct file_operations xxx_fops = {
    .owner = THIS_MODULE,
    .read = xxx_read,
    .write = xxx_write,
    .unlocked_ioctl = xxx_ioctl,
    .open = xxx_open,
    .release = xxx_close,
    ……
};

(3)初始化cdev

    cdev_init(&xxx_dev.cdev, xxx_fops);
    xxx_dev.cdev.owner = THIS_MODULE;

(4)获取字符设备号

    if (xxx_major) {
        register_chrdev_region(xxx_dev_no, 1, DEV_NAME);
    } else {
        alloc_chrdev_region(&xxx_dev_no, 0, 1, DEV_NAME);
    }

(5)注册设备

    ret = cdev_add(&xxx_dev.cdev, xxx_dev_no, 1);

讲完了字符设备驱动的初始化流程,该来看一下块设备驱动的初始化流程了。

块设备的核心结构为struct block_device(说实在的,从这名字上就想怼这帮做内核的。至少两边要对应起来嘛,要全称就都用全称:struct char_device、struct block_device;要简称就都用简称:struct cdev、struct bdev或者struct blkdev。结果弄了一个字符设备用简称,块设备用全称,不伦不类),其在include/linux/blk_types.h中定义,代码如下:

struct block_device {
	sector_t		bd_start_sect;
	sector_t		bd_nr_sectors;
	struct gendisk *	bd_disk;
	struct request_queue *	bd_queue;
	struct disk_stats __percpu *bd_stats;
	unsigned long		bd_stamp;
	bool			bd_read_only;	/* read-only policy */
	u8			bd_partno;
	bool			bd_write_holder;
	bool			bd_has_submit_bio;
	dev_t			bd_dev;
	struct inode		*bd_inode;	/* will die */

	atomic_t		bd_openers;
	spinlock_t		bd_size_lock; /* for bd_inode->i_size updates */
	void *			bd_claiming;
	void *			bd_holder;
	const struct blk_holder_ops *bd_holder_ops;
	struct mutex		bd_holder_lock;
	/* The counter of freeze processes */
	int			bd_fsfreeze_count;
	int			bd_holders;
	struct kobject		*bd_holder_dir;

	/* Mutex for freeze */
	struct mutex		bd_fsfreeze_mutex;
	struct super_block	*bd_fsfreeze_sb;

	struct partition_meta_info *bd_meta_info;
#ifdef CONFIG_FAIL_MAKE_REQUEST
	bool			bd_make_it_fail;
#endif
	bool			bd_ro_warned;
	/*
	 * keep this out-of-line as it's both big and not needed in the fast
	 * path
	 */
	struct device		bd_device;
} __randomize_layout;

上回书说过,块设备驱动比字符设备要复杂得“多地多”(单田芳评书的味道~)。从上边这俩设备的核心结构体定义上,你就能看出来块设备复杂了多少。因此,在流程上也有较大的区别。具体来对照字符设备驱动流程来看一下。块设备驱动的一般初始化流程如下:

(0)加载设备驱动

static int __init xxx_init(void)
{
    ……
}

module_init(xxx_init);

这一步还是一样。

(1)初始化并准备block_device_operations结构中的成员

static int xxx_open(struct block_device *bdev, fmode_t mode)
{
    struct xxx_dev *dev = bdev->bd_disk->private_data;
    ……
    return 0;
}

static void xxx_release(struct gendisk *disk, fmode_t mode)
{
    struct xxx_dev *dev = disk->private_data;
    ……
}

static int xxx_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
    ……
}

struct block_device_operations xxx_ops = {
    .open = xxx_open,
    .release = xxx_release,
    .ioctl = xxx_ioctl,
    ……
}

块设备驱动的open函数与字符设备驱动的对等体不太相似。前者不以相关的inodehe file结构体指针作为参数,因为file和inode概念位于文件系统层中。

static int xxx_open(struct inode *inode, struct file *filp)
{
    filp->private_data = ……;
    ……
}

(2)块设备注册

    if (register_blkdev(XXX_MAJOR, "xxx")) {
        error = -EIO;
        goto out;
    }

(3)请求队列初始化

    xxx_queue = blk_init_queue(xxx_request, xxx_lock);
    if (!xxx_queue)
        goto out_queue;
    blk_queue_max_hw_sectors(xxx_queue, 255);
    blk_queue_logical_block_size(xxx_queue, 512);

(4)gendisk初始化

    xxx_disks->major = XXX_MAJOR;
    xxx_disks->first_minor = 0;
    xxx_disks->fops = &xxx_op;
    xxx_disks->queue = xxx_queue;
    sprintf(xxx_disks, xxx_size * 2);
    add_disk(xxx_disks); // 添加gendisk

至此,借着与字符设备初始化流程的对比,块设备初始化的一般流程就基本清楚了。当然,这只是一个总体的概况,接下来会对于此流程以及整个块设备驱动的细节进行深入解析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1512648.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探索人工智能的现状与未来:机遇与挑战

🍎个人博客:个人主页 🏆个人专栏:日常聊聊 ⛳️ 功不唐捐,玉汝于成 目录 正文 人工智能的现状 人工智能的应用领域 人工智能的未来 人工智能面临的挑战 我的其他博客 正文 人工智能(AI&#xff09…

空间计算综合指南

空间计算(spatial computing)是指使人类能够在三维空间中与计算机交互的一组技术。 该保护伞下的技术包括增强现实(AR)和虚拟现实(VR)。 这本综合指南将介绍有关空间计算所需了解的一切。 你将了解 AR、VR…

【yolov8和yolov5】用命令快速着手训练

文章目录 1.yolov81.1.创建conda环境1.2.下载代码和环境1.3.YOLOv8训练、自测和预测的代码及解释1.3.1. YOLOv8 训练代码:1.3.2.yolov8 自测代码:1.3.3.yolov8 推理代码:1.3.4.注意: 2.yolov52.1.创建conda环境2.2.下载代码和环境…

在项目管理中,如何更好地协同团队成员,提高团队合作效率?

在项目管理中,协同团队成员并提高团队合作效率是确保项目成功实施的关键。以下是一些建议,有助于更好地协同团队成员,提高团队合作效率: 一、明确角色与责任 为每个团队成员分配明确的角色和职责,通过制定详细的任务…

Kafka MQ 如何处理请求

Kafka MQ 如何处理请求 元数据请求 客户端怎么知道该往哪里发送请求呢? 客户端使用了另一种请求类型,也就是元数据 请求。这种请求包含了客户端感兴趣的主题列表。服务器端的响应消息里指明了这些主题 所包含的分区、每个分区都有哪些副本,以及哪个副…

基于java+springboot开发的计算机毕业设计网文论坛管理系统设计与实现【附源码】

基于javaspringboot开发的计算机毕业设计网文论坛管理系统设计与实现【附源码】 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联…

HTML静态网页成品作业(HTML+CSS)——游戏战地介绍设计制作(4个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有4个页面。 二、作品演示 三、代…

视频AI方案:数据+算力+算法,人工智能的三大基石

背景分析 随着信息技术的迅猛发展,人工智能(AI)已经逐渐渗透到我们生活的各个领域,从智能家居到自动驾驶,从医疗诊断到金融风控,AI的应用正在改变着我们的生活方式。而数据、算法和算力,正是构…

Matplotlib中的子图:规划绘图的指南和工具

导 读 我最近从事一个项目,需要在 matplotlib 中进行一些微调的子图和叠加。虽然我对制作基本的可视化感到很舒服,但我很快发现我对子图系统的理解没有达到标准。于是回到基础知识,并花了一些时间阅读文档并在 Stack Overflow 上搜索相关示例…

算法-前缀和-562. 壁画

题目 思路 被毁掉的墙段一定只与一段还未被毁掉的墙面相邻只能从两头坏,因为如果从中间坏的话,毁掉的墙就和两段未被毁掉的墙面相邻了,画了的墙是坏不了的,只能坏没有画的墙结果为n/2 向上取整,求取总和最大值 代码 T int(inp…

一台GTX1080显卡的怪兽,我可不能错过这个机会!

标题:我花了30块钱买了一台电脑主机。 这个配置能赚钱吗? 1. 收购惊喜 那是一个阳光明媚的下午,我在水管修理店里闲逛。 突然,一位老顾客手里拿着一台旧电脑主机匆匆走了进来。 他说:“小王,你能帮我看看…

【Kimi帮我看论文(四)】TransE:Translating Embeddings for Modeling Multi-relational Data

一、论文信息 1 标题 Translating Embeddings for Modeling Multi-relational Data 2 作者 Antoine Bordes, Nicolas Usunier, Alberto Garcia-Durn, Jason Weston, Oksana Yakhnenko 3 研究机构 Universit de Technologie de Compigne – CNRS Heudiasyc UMR 7253 Compi…

绝地求生:PUBG官方公布2024工作计划

大家好,我是闲游盒。 首先今天官方公布了2024工作计划,下面我们一起来了解一下2024工作重点,官方提到的2点:一是通过对PUBG的维护和优化来改善线上服务的质量,二是为玩家们提供更加多姿多彩的游戏体验。我个人看完了全…

EMQX+InfluxDB+Grafana 构建物联网可视化平台

EMQXInfluxDBGrafana 构建物联网可视化平台 本文以常见物联网使用场景为例,介绍了如何利用 EMQ X MQTT 服务器 InfluxDB Grafana 构建物联网数据可视化平台,将物联网设备上传的时序数据便捷地展现出来。 在物联网项目中接入平台的设备数据和数据存储…

第0章 学习包介绍

一、考试介绍 二、考点分析 白盒测试、黑盒测试、面向对象测试、web测试;下午题考的概率很大; 上午题考点: 三、资料包 四、如何学习

揭秘小红书口碑营销策略,品牌营销总结

口碑营销,是品牌方获得消费者的必修课之一,尤其是在小红书平台上,毕竟小红书是精准消费者扎堆的地方。但是,小红书营销该怎么做才能保证展示率!怎么才能树立品牌方的正面形象,作为品牌方对这个问题还是比较模糊&#x…

【Java设计模式】十七、状态模式

文章目录 1、背景案例2、状态模式3、案例4、总结 1、背景案例 现要按钮控制电梯的四种状态:开门、关门、启动、停止。但每种状态的改变,可能受其他状态影响,如运行状态下,不能进行开门。写个普通实现: 定义电梯接口 …

项目管理系统推荐:打造高效团队协作!教育科技公司管理利器揭秘

教育科技行业是指利用先进的技术手段和教育理论,为教育提供更加高效、便捷、个性化的解决方案。新东方、学而思、高顿都是耳熟能详的教育科技公司。项目管理、团队协作都离不开项目管理系统。适合教育科技公司的项目管理系统,项目管理系统推荐。 常见的项…

BUG:RuntimeError: input.size(-1) must be equal to input_size. Expected 1, got 3

出现的bug为:RuntimeError: input.size(-1) must be equal to input_size. Expected 1, got 3 出现问题的截图: 问题产生原因:题主使用pytorch调用的nn.LSTM里面的input_size和外面的数据维度大小不对。问题代码如下: self.lstm nn.LSTM(input_size, hidden_size, num_laye…

VS 调试Hololens 2工程报错 有未经处理的异常: Microsoft C++ 异常:

原因是unity 少安装了XR工具包 安装完后重新用unity打包,然后vs打开打包出来的工程,电脑和眼镜用usb连接,直接运行调试就可以了