嵌入式Linux(7):字符设备驱动--申请设备号

2023-05-16

文章目录

  • 1、字符设备和杂项设备的区别
  • 2、注册字符类设备号的两个办法
    • 第一种:静态分配一个设备号
    • 第二种:动态分配
    • 注销设备号
  • 写代码
    • 不带参数测试(动态分配):
    • 带参数测试(静态设置):
  • 建议使用动态设备号的办法

1、字符设备和杂项设备的区别

  1. 杂项设备的主设备号是固定的,固定为10;字符类设备就需要自己或者系统来给我们分配主设备号。
  2. 杂项设备可以自动生成设备节点,字符设备需要我们自己生成设备节点。
  3. 代码量的角度来说,字符设备要比杂项设备代码量要多,因为多了分配设备号和自己生成设备节点这两步。

2、注册字符类设备号的两个办法

第一种:静态分配一个设备号

使用的函数:
register_chrdev_region(dev_t from, unsigned count, const char * name)
参数:

  • 第一个:设备号的起始值。类型是dev_t类型。
  • 第二个:次设备号的个数。
  • 第三个:设备的名称。如:1 mem mem就是设备名称。
    返回值:成功返回0,失败访问非0。

cat /proc/devices
1 mem
4 /dev/vc/0
4 tty

dev_t (linux/types.h)类型:是用来保存设备号的,是一个32位数。
高12位是用来保存主设备号,低20位是用来保存次设备号的。

typedef u32 __kernel_dev_t;
typedef __kernel_dev_t		dev_t;

需要明确知道系统里面的哪些设备号没有被使用。

Linux提供了几个宏定义来操作设备号。

#define MINORBITS 20

次设备号的位数,一共是20位

#define MINORMASK ((1U<<MINORBITS)-1)

次设备号的掩码

#define MAJOR(dev) ((unsigned int)((dev) >> MINORBITS)

获取主设备号。

#define MINOR(dev) ((unsigned int)((dev) & MINORMASK))

获取次设备号。

#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))

将我们的主设备号和次设备号组成一个dev_t类型。第一个参数是主设备号,第二个参数是次设备号。

第二种:动态分配

使用的函数是:

alloc_chrdev_region(dev_t * dev, unsigned baseminor, unsigned count, const char * name)

参数:

  • 第一个:保存生成的设备号。
  • 第二个:请求的第一个次设备号,通常是0。
  • 第三个:连续申请的设备号的个数。
  • 第四个:设备名称。
    返回值:成功返回0,失败访问非0

使用动态分配会优先使用255~234

注销设备号

使用的函数是:

unregister_chrdev_region(dev_t, unsigned);

参数:

  • 第一个:申请的设备号的起始地址。
  • 第二个:申请的连续的设备号的个数。

写代码

功能描述:

  • 代码根据模块加载时是否带参数而确定是使用动态加载设备号还是静态加载设备号。模块加载时后面的参数是主设备号。

chrdev.c

#include <linux/init.h> // 包含宏定义
#include <linux/module.h> // 包含初始化、加载模块的头文件
#include <linux/fs.h>
#include <linux/kdev_t.h>

#define DEVICE_NUMBER 1
#define DEVICE_SNAME   "schrdev"
#define DEVICE_ANAME   "achrdev"

#define DEVICE_MINOR_NUMBER  0

static int major_num, minor_num;

module_param(major_num, int, S_IRUSR);
module_param(minor_num, int, S_IRUSR);


static int hello_init(void)
{
    dev_t dev_num;
    int ret;

    if(major_num)
    {
        printk("major_num: %d\n", major_num);
        printk("minor_num: %d\n", minor_num);

        dev_num = MKDEV(major_num, minor_num);

        ret = register_chrdev_region(dev_num, DEVICE_NUMBER, DEVICE_SNAME);

        if(ret < 0)
        {
            printk("register_chrdev_region error\n");
        }
        else
            printk("register_chrdev_region ok\n");
    }
    else
    {
        ret = alloc_chrdev_region(&dev_num, DEVICE_MINOR_NUMBER, DEVICE_NUMBER, DEVICE_ANAME);
        if(ret <0)
        {
            printk("alloc_chrdev_region error\n");
        }
        else
            printk("alloc_chrdev_region ok\n");

        major_num = MAJOR(dev_num);
        minor_num = MINOR(dev_num);

        printk("major_num: %d\n", major_num);
        printk("minor_num: %d\n", minor_num);
    }

	printk("major_num = %d, minor_num = %d\n",major_num, minor_num);
	return 0;
}
static void hello_exit(void)
{
    unregister_chrdev_region(MKDEV(major_num, minor_num), DEVICE_NUMBER);
	printk("Bye Bye\n");
}

/* 模块的入口 */
module_init(hello_init);
/* 模块的出口 */
module_exit(hello_exit);

/* 模块声明 */
MODULE_LICENSE("GPL");

Makefile

# 定义内核源码的目录
KERN_DIR ?= /home/liefyuan/Linux/rk356x_linux/kernel
# 定义当前目录
PWD        := $(shell pwd)
# 要生成的内核模块
obj-m += chrdev.o

all:
	make -C $(KERN_DIR) M=$(PWD) modules

clean:
	rm -rf *.order *o *.symvers *.mod.c *.mod *.ko

编译:

export ARCH=arm64 
export CROSS_COMPILE=aarch64-linux-gnu-
make

运行测试:

不带参数测试(动态分配):

[root@RK356X:/opt]# insmod chrdev.ko
[26656.968890] alloc_chrdev_region ok
[26656.968998] major_num: 236
[26656.969006[root@RK356X:/opt]# ] minor_num: 0
[26656.969014] major_num = 236, minor_num = 0

[root@RK356X:/opt]# rmmod chrdev
[26987.753632] Bye Bye

可以看出设备号被优先分配到255~234的范围内。

带参数测试(静态设置):

[root@RK356X:/opt]# insmod chrdev.ko major_num=235 minor_num=1
[27157.343387] major_num: 235
[27157.343491] minor_num: 1
[27157.343504[root@RK356X:/opt]# ] register_chrdev_region ok
[27157.343512] major_num = 235, minor_num = 1

[root@RK356X:/opt]# rmmod chrdev.ko
[27170.387528] Bye Bye

建议使用动态设备号的办法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式Linux(7):字符设备驱动--申请设备号 的相关文章

  • 电路中的常见符号总结

    嵌入式如何阅读原理图和数据手册 路溪非溪的博客 CSDN博客 硬件原理图常见缩写 EN xff1a Enable xff0c 使能 CS xff1a Chip Select xff0c 片选 RST xff1a Reset xff0c 重启
  • 嵌入式常见英文2500词总结

    目录 嵌入式硬件常见英文总结 嵌入式软件常见英文总结 电子技术专业英语 嵌入式硬件常见英文总结 block diagram xff0c 框图 figure xff0c 图形 xff0c 图标 processor xff0c 处理器 Mirr
  • 我的2013—弃金融IT,从SAP业务

    我的2013 xff0c 是动荡的一年 xff1b 这一年 xff0c 我跳巢了 xff1b 这一年 xff0c 我换行业了 xff1b 这一年 xff0c 我离开了生活5年的长春 xff0c 来到成都 xff1b 这一年 xff0c 我放
  • STM32实战总结:HAL之电机

    电机基础知识参考 xff1a 51单片机外设篇 xff1a 电机 路溪非溪的博客 CSDN博客 无刷电机和有刷电机 先详细了解有刷电机 xff1a 带你了解 xff08 有刷 xff09 电机工作原理 哔哩哔哩 bilibili 再详细了解
  • F407标准库之时钟系统

    主要参考正点原子数据手册和源码资料等 第19讲 STM32时钟系统精讲 哔哩哔哩 bilibili 此处记录较为重要或者较易出错的一些遗漏之处 xff0c 作为补充 一般而言 xff0c 时钟越高 xff0c 速度越快 xff0c 但同时抗
  • F407标准库之定时器

    主要参考正点原子数据手册和源码资料等 第31 通用定时器基本原理讲解 哔哩哔哩 bilibili 此处记录较为重要或者较易出错的一些遗漏之处 xff0c 作为补充 定时器中断 定时器相关的库函数主要集中在固件库文件 stm32f4xx ti
  • F407标准库之基础知识

    关于STM32的结构体封装 在STM32中 xff0c 有两种容易弄混的结构体封装 第一种是系统对底层寄存器的封装 结构体类型定义好之后 xff0c 是不会分配地址空间的 xff0c 此时只是个类型定义 xff0c 之后使用的时候 xff0
  • c++架构师需要掌握哪些知识

    目录 本文技术梳理主要针对于三类人群的技术需求 c c 43 43 Linux服务器端开发岗位分析 经常被问到的问题 xff1a 技术体系建立的好处 c c 43 43 Linux服务器开发技术学习路径 一 精进基石 二 高性能网络设计 三
  • cmake:使用execute_process调用shell命令或脚本

    CMake可以通过execute process调用shell命令或者脚本 xff0c 其原型如下 xff1a execute process COMMAND lt cmd1 gt args1 COMMAND lt cmd2 gt args
  • 树莓派3B+上安装ubutun mate 18.04.2

    1 准备16G以上储存卡 xff0c 读卡器 2 准备两个软件 xff1a SDCardFormatter Win32DiskImager分别用于储存卡格式化和写入系统文件 链接如下 xff1a 链接 xff1a https pan bai
  • linux应用编程--思维导图

    思维导图软件是xmind 下载源文件点击打开链接
  • 深度学习中Batch、Iteration、Epoch的概念与区别

    在神经网络训练中 xff0c 一般采用小批量梯度下降的方式 Batch Epoch Iteration 就是其中的重要的概念 我们要理解懂得它们都是什么以及它们之间的区别 1 Batch 每次迭代时使用的一批样本就叫做一个Batch xff
  • STM32使用CubeMAX配置的串口中断接收方法

    STM32使用CubeMAX配置的串口中断接收方法 目录 1 定位串口中断发生的地方 2 处理串口中断接收的流程是 xff1a xff08 1 xff09 初始化串口 xff08 2 xff09 在main中第一次调用接收中断函数 xff0
  • SAP 寻找增强点的方法

    SAP中寻找增强的实现方法 SAP 增强已经发展过几代了 xff0c 可参考 SAP 标准教材 BC425 和 BC427 简单的说SAP的用户出口总共有四 代 1 第一代 基于源代码的增强 SAP提供一个空代码的子过程 xff0c 在这个
  • SNMPV3的实现原理

    在snmp发展到V3版本后 xff0c 把snmp的安全性提升到一个新高度 xff0c 这同时也带来了实现上的复杂性 在02年 xff0c 03年我都曾经想进一步的了解它的实现 xff0c 但都没什么进展 这次在实现Csnmp的过程中 xf
  • ubuntu更新错误:dists/artful/main/binary-arm64/Packages 404 Not Found

    Failed to fetch http archive ubuntu com ubuntu dists artful main binary arm64 Packages 404 Not Found IP 91 189 88 162 80
  • 个人公众号开通啦!!!!

    已经开通了个人微信公众号 xff1a 编程时光机 以后会在公众号里和大家分享知识和生吞活 xff0c 欢迎大家关注 xff01 xff01
  • 小白学AI系列(一)-- AI简史

    经过一段时间的酝酿 xff0c 小白学AI系列也正是开始了 xff01 小编将从三个阶段和大家一起入门人工智能 xff0c 掌握常用机器学习算法和数据分析技巧 小编专业为数据融合方向 xff0c 也曾接触过机器学习 xff0c 但由于人工智
  • 小白学AI系列(二) -- Python模块和函数

    原文地址 xff1a 小白学AI系列 xff08 二 xff09 Python模块和函数 今天的内容是带大家学习解释性语言 Python 小编有学过一段时间的C 43 43 和Matlab 相对于二者而言 xff0c Python是作为学习
  • PX4固定翼调试校准流程及实验相关问题记录分析

    pixhawk固定翼调试流程 对于px4固件 xff0c 其对应选择的一般是qgroundcontrol地面站 xff08 APM一般使用Mission Planner xff09 本次调试的固件版本是1 6 5dev xff08 最新的固

随机推荐

  • Ubuntu16.04下PX4环境快速搭建及uORB通信机制

    Ubuntu16 04下的环境搭建 之前搭建PX4环境常常编译不通 xff0c cmake gcc 以及交叉编译器gcc arm none eabi的版本问题导致make固件报错 xff0c 好不容易编译通过了 xff0c 在进行安装jMA
  • PX4固件通过UART连接串口读取超声波,和树莓派3通信

    添加串口读取程序 首先在Firmware msg文件夹下添加rw uart msg span class hljs keyword char span span class hljs number 5 span datastr span c
  • PX4自主飞行相关问题

    调试入坑 赶在回去之前把10月1日新校区试飞相关问题记录一下 首先是调试相关问题 调试具体流程 在校准遥控器时经常出现校准一半就停止的问题 xff0c 期初认为是固件问题 xff0c 换了1 6 5 1 6 3 xff0c 1 5 5三个固
  • PID控制器及其C++实现

    PID控制器原理 PID控制器实际上是对偏差的控制 其原理图如下 其数学的表达如下 u x 61 K p e r r t 43 1 T e r r t d t 43 T D d e r r t d t u x
  • Oracle Systimestamp 函数

    在Oracle PLSQL中 xff0c Systimestamp 函数返回本机数据库上当前系统日期和时间 包括微秒和时区 Systimestamp 函数的语法是 xff1a systimestamp 应用于 xff1a Oracle 9i
  • px4源码解读之fw_att_control

    目录 程序和控制流程源码解读总结 程序和控制流程 个人简单的总结了一下整个程序的流程如下 整个的控制流程图可以在官网中找到 源码解读 在解读源码之前 需要提几个公式 第一个就是协调转弯中的偏航控制 也就是流程图中为什么输入是空速 p 61
  • 安装Mavlink generator出现UnicodeEncodeError错误

    最近在看mavlink 在执行官网的操作时出现了问题 问题如下 span class hljs constant Exception span span class hljs keyword in span span class hljs
  • mc_att_control基础知识:向量运算和罗德里格斯旋转

    向量的叉乘和点乘 在我们的mc att control中有我们的向量的点乘和叉乘 一般遇到的都是三维的运算 S O 3 S O 3 李群 向量点乘 假设向量 a 61 a 1 a 2 a 3
  • 低通滤波器和高通滤波器的程序实现原理推导

    傅立叶变换 拉普拉斯变换和Z变换 对于信号分析而言 傅立叶变换是必不可少的 我们都知道傅立叶变换是把系统从时域变换到频域进行分析 那么拉普拉斯变换和Z变换是干什么的 简单的来说 由于傅里叶变换的收敛有一个狄利克雷条件 xff0c 要求信号绝
  • PX4源码解读之fw_pos_control_l1

    固定翼的位置控制是一个很重要问题 它不同于旋翼的控制 需要对速度和高度进行解耦控制 并且其不能像旋翼那样进行悬停 其转弯的时候有一个转弯半径 本博客不会对源码进行详细的解读 主要是分享一些自己读源码时的资料 自己读的过程中也有注释 想要的同
  • 四元数表示旋转的理解

    哈密尔顿 为了纪念四元数的发明者哈密尔顿 爱尔兰于1943年11月15日发行了下面这张邮票 哈密尔顿简直是个天才 哈密尔顿从小到进入大学之前没有进过学校读书 xff0c 他的教育是靠叔父传授以及自学 他找到了法国数学家克莱罗 xff08 C
  • mc_att_control源码解析

    目录 源码分析内环控制外环控制 之前写了博客分析了一下旋翼姿态控制的基础知识 mc att control基础知识 这次就对照代码将整个旋翼姿态控制过程呈现一遍 先看一下整个程序的框图 从图中可以看到 实际上整个控制分成内外两个环进行控制
  • PX4下载指定版本代码和刷固件的三种方式

    由于之前下载的是1 7版本的代码 现在v5版本的px4需要最新的代码固件 因此这里记录一下 查看自己代码版本 查看自己仓库代码版本的命令如下 git describe always tags 输出 v1 7 0 rc3 9 g0e1c7eb
  • Python怎么调用matlab的

    文章目录 环境的安装安装合适的python环境安装用于 Python 的 MATLAB 引擎 API 环境的安装 安装合适的python环境 研究这个也是在知乎上突然看到的 xff0c 以前python写的多 xff0c 现在由于工作需要
  • insert语句中sequence的使用方法

    我们常常在表中需要插入一些自动增长的值 一方面 我们可以手动添加这些值 xff0c 另一方面 oracle提供的sequence可以帮助我们实现插入的值自动增长 而不需要我们手动的提供值 我们需要做的就是设置好sequence的初值和增长值
  • Ubuntu 安装 vnc server

    查看Ubuntu系统版本 xff1a sudo lsb release a 安装Xfce桌面环境 xff1a sudo apt install xfce4 xfce4 goodies 配置gnome桌面环境 xff0c 参考 xff1a h
  • 嵌入式Linux(4):应用层和内核层数据传输

    文章目录 简介1 如果在应用层使用系统IO对设备节点进行打开 xff0c 关闭 xff0c 读写等操作会发生什么呢 xff1f 写个例子2 假如驱动层的file operations里面没有实现read之类的操作函数 xff0c 会发生什么
  • 嵌入式Linux(5):物理地址到虚拟地址映射

    文章目录 理论知识1 使能了MMU以后有什么好处呢 xff1f 2 MMU非常复杂 xff0c 那么我们如何完成物理地址到虚拟地址的转换呢 xff1f 3 如何查看哪些物理地址被映射过了呢 xff1f 实例 RK3568 理论知识 在Lin
  • 嵌入式Linux(6):驱动模块传参

    文章目录 1 什么是驱动传参 xff1f 2 驱动传参有什么作用 xff1f 3 怎么给我们的驱动传参数 xff1f 传递普通参数传递数组 1 什么是驱动传参 xff1f 驱动传参就是在安装驱动模块 xff08 ko文件 xff09 的时候
  • 嵌入式Linux(7):字符设备驱动--申请设备号

    文章目录 1 字符设备和杂项设备的区别2 注册字符类设备号的两个办法第一种 xff1a 静态分配一个设备号第二种 xff1a 动态分配注销设备号 写代码不带参数测试 xff08 动态分配 xff09 xff1a 带参数测试 xff08 静态