韦东山Linux驱动入门实验班(3)hello驱动---申请指定数量的次设备号

简介: 韦东山Linux驱动入门实验班(3)hello驱动---申请指定数量的次设备号

前言

(1)前面我们介绍了如何自动产生设备节点,详细分析了驱动层代码。但是我们有没有发现一个问题,我们每次设备节点的主设备号都是240,次设备号是0。主设备能够理解,这个是系统自动分配的,那么为什么次设备号永远是0呢?我能不能是其他的?

(2)答案是可以的。


什么是Linux设备号

(1)为了方便管理, Linux 中每个设备都有一个设备号,设备号由主设备号和次设备号两部分组成,主设备号表示某一个具体的驱动,次设备号表示使用这个驱动的各个设备。

(2)Linux 提供了一个名为 dev_t 的数据类型表示设备号,而dev_t 其实就是 unsigned int 类型,是一个 32 位的数据类型。

(3)这 32 位的数据构成了主设备号和次设备号两部分,其中高 12 位为主设备号,第 20 位为次设备号。

(4)因此 Linux系统中主设备号范围为 0~4095。


如何动态分配设备号

alloc_chrdev_region()简单介绍

(1)首先需要知道register_chrdev()对于设备号的申请规则是什么。==在register_chrdev()中,他只会申请到一个没有被使用到的主设备号,及其他之下的所有次设备号。==我们会发现,这样太占用次设备号资源。

(2)所以这里要做的是,申请一个主设备号和指定的次设备号,这一部分用于注册驱动程序。我们也就需要了解alloc_chrdev_region()函数。


  /*申请一个主次设备号空间,这个区域给当前驱动使用,主设备号和次设备号存入第一个参数中
   *参数一 :第一个设备的主设备号和次设备号
   *参数二 : 从哪个次设备号开始
   *参数三 :想获得几个次设备号
   *参数四 :驱动程序名
   *返回值:如果申请失败,返回一个负数
  */
  ret = alloc_chrdev_region(&dev, 0, 2, "hello");

cdev_add()简单介绍

(1)我们申请到了设备号,还需要将设备号传递给驱动,所以需要使用到cdev_add()函数。

(2)而这个传递是如何进行的呢?这里就需要引入一个cdev结构体,这个结构体用于描述一个字符设备,我们需要将设备号传递给这个结构体。

struct cdev {
  struct kobject kobj;
  struct module *owner;
  const struct file_operations *ops;
  struct list_head list;
  dev_t dev;
  unsigned int count;
 };
static struct cdev hello_cdev; //用于表示一个字符设备
  /*申请完设备号之后,需要进行
   *参数一 : 要增加的cdev
   *参数二 : 将主次设备号dev传入
   *参数三 : 决定占用几个主次设备号,这里占2个主次设备号
   *返回值 : 如果返回值不是0,表示错误
  */
    ret = cdev_add(&hello_cdev, dev, 2);

cdev_init()简单介绍

(1)我们的字符设备拥有了设备号之后,还需要file_operations结构体,用于进行描述这个驱动如何使用。

(2)所以这个时候,就需要使用到cdev_init()函数,将file_operations结构体传递给cdv结构体。

static const struct file_operations hello_drv = {
    .owner      = THIS_MODULE,
  .read   = hello_read,
  .write    = hello_write,
  .open   = hello_open,
    .release    = hello_release,
};
  //申请完设备号之后,需要进行初始化。初始化cdev,让cdev与file_operations结构体挂钩
    cdev_init(&hello_cdev, &hello_drv);


cdev_del()

这个就是用来删除cdev 的。传入cdev结构体即可

unregister_chrdev_region()

这个是将申请到的主次设备号空间释放


本章与上一章的改动之处

(1)驱动安装:

<1>上一章在进行次设备号的分配上,是直接采用的register_chrdev()函数进行分配。这种方法会导致所有次设备号都被占用。

<2>于是我们这一章,将使用 alloc_chrdev_region(),cdev_add()和cdev_init()函数来代替register_chrdev()函数。

(2)删除驱动:

<1>在上一章中,我们删除驱动是调用的unregister_chrdev()函数。

<2>而在我们当前这一章节,需要使用cdev_del()删除cdev,然后调用unregister_chrdev_region()释放主次设备号。


/********  驱动安装   ********/
/*
 *原来
*/
major = register_chrdev(0, "100ask_hello", &hello_drv);
/*
 *现在
*/
    // 如果是register_chrdev,那么会申请到一个主设备号,以及他的所有次设备号。那样太占用次设备号资源
    // 所以这里要做,申请一个主设备号和指定的次设备号,这一部分用于注册驱动程序
  /*申请一个主次设备号空间,这个区域给当前驱动使用,主设备号和次设备号存入第一个参数中
   *参数一 :第一个设备的主设备号和次设备号
   *参数二 : 从哪个次设备号开始
   *参数三 :想获得几个次设备号
   *参数四 :驱动程序名
   *返回值:如果申请失败,返回一个负数
  */
  ret = alloc_chrdev_region(&dev, 0, 2, "hello");
  //判断是否申请主次设备号成功,如果失败进入
  if (ret < 0) 
  {
    //打印无法获得设备号
    printk(KERN_ERR "alloc_chrdev_region() failed for hello\n");
    //返回无效参数
    return -EINVAL;
  }
  //申请完设备号之后,需要进行初始化。初始化cdev,让cdev与file_operations结构体挂钩
    cdev_init(&hello_cdev, &hello_drv);
  /*申请完设备号之后,需要进行
   *参数一 : 要增加的cdev
   *参数二 : 将主次设备号dev传入
   *参数三 : 决定占用几个主次设备号,这里占2个主次设备号
   *返回值 : 如果返回值不是0,表示错误
  */
    ret = cdev_add(&hello_cdev, dev, 2);
  //如果返回值不为0,打印错误
  if (ret)
    {
    //打印增加cdev失败
    printk(KERN_ERR "cdev_add() failed for hello\n");
    //返回无效参数
    return -EINVAL;
    }
/********  驱动卸载   ********/
/*
 *原来
*/
  //卸载驱动程序
  //第一个参数是主设备号,第二个是名字
    unregister_chrdev(major, "100ask_hello");
/*
 *现在
*/
    //删除cdev
    cdev_del(&hello_cdev);
  //将申请到的主次设备号空间释放
    unregister_chrdev_region(dev, 2);
相关文章
|
2月前
|
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
93 0
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
Linux设备命令行运维工具WowKey问答
WowKey 是一款用于 Linux 设备运维的工具,可通过命令行手动或自动执行指令剧本,实现批量、标准化操作,如健康检查、数据采集、配置更新等。它简单易用,只需编写 WIS 指令剧本和 APT 帐号密码表文件,学习成本极低。支持不同流派的 Linux 系统,如 RHEL、Debian、SUSE 等,只要使用通用 Shell 命令即可通吃Linux设备。
试试Linux设备命令行运维工具——Wowkey
WowKey 是一款专为 Linux 设备设计的命令行运维工具,提供自动化、批量化、标准化、简单化的运维解决方案。它简单易用、高效集成且无依赖,仅需 WIS 指令剧本文件、APT 账号密码文件和 wowkey 命令即可操作。通过分离鉴权内容与执行内容,WowKey 让运维人员专注于决策,摆脱繁琐的交互与执行细节工作,大幅提升运维效率与质量。无论是健康检查、数据采集还是配置更新,WowKey 都能助您轻松应对大规模设备运维挑战。立即从官方资源了解更多信息:https://atsight.top/training。
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
5月前
|
Linux新手入门手册
在Linux或类Unix系统中,掌握一系列基础命令和快捷键是提升工作效率的关键。这些工具和技巧不仅能帮助用户更高效地管理系统,还能在日常使用中带来极大的便利。以下是对这些基础操作与快捷键的详细解析大全。
99 9
linux入门!
本文档介绍了Linux系统入门的基础知识,包括操作系统概述、CentOS系统的安装与远程连接、文件操作、目录结构、用户和用户组管理、权限管理、Shell基础、输入输出、压缩打包、文件传输、软件安装、文件查找、进程管理、定时任务和服务管理等内容。重点讲解了常见的命令和操作技巧,帮助初学者快速掌握Linux系统的基本使用方法。
494 3
|
18天前
|
Linux命令拓展:为cp和mv添加进度显示
好了,就这样,让你的Linux复制体验充满乐趣吧!记住,每一个冷冰冰的命令背后,都有方法让它变得热情起来。
58 8
Linux环境下必备的基础命令概览
以上就是Linux系统中的基本命令和工具,掌握它们就能帮你在Linux世界里游刃有余。这其实就像是学习驾驭一辆新车,熟悉了仪表盘,调整好了座椅,之后的旅程就只需要享受风驰电掣的乐趣了。
42 4
linux命令—tree
tree是一款强大的Linux命令行工具,用于以树状结构递归展示目录和文件,直观呈现层级关系。支持多种功能,如过滤、排序、权限显示及格式化输出等。安装方法因系统而异常用场景包括:基础用法(显示当前或指定目录结构)、核心参数应用(如层级控制-L、隐藏文件显示-a、完整路径输出-f)以及进阶操作(如磁盘空间分析--du、结合grep过滤内容、生成JSON格式列表-J等)。此外,还可生成网站目录结构图并导出为HTML文件。注意事项:使用Tab键补全路径避免错误;超大目录建议限制遍历层数;脚本中推荐禁用统计信息以优化性能。更多详情可查阅手册mantree。
linux命令—tree
linux命令—ls
`ls` 是 Linux 系统中用于列出目录内容的基础命令,功能强大且使用频率极高。它可以帮助用户查看文件、分析磁盘空间及检查权限等。常用选项如 `-l` 显示详细信息,`-a` 包含隐藏文件,`-h` 以易读格式展示大小,`-t` 按修改时间排序等。通过组合选项,可实现复杂需求,如递归遍历目录(`-R`)、显示 inode 号(`-i`)或结合正则过滤特定文件。注意权限限制、特殊字符处理及大规模目录操作可能带来的性能问题。掌握 `ls` 是高效使用 Linux 的关键一步。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问