您的位置:首页 > 游戏 > 手游 > 网页制作软件名称_成立公司需要什么条件_品牌推广方案思维导图_免费独立站自建站网站

网页制作软件名称_成立公司需要什么条件_品牌推广方案思维导图_免费独立站自建站网站

2025/4/27 20:36:52 来源:https://blog.csdn.net/ItJavawfc/article/details/147074325  浏览:    关键词:网页制作软件名称_成立公司需要什么条件_品牌推广方案思维导图_免费独立站自建站网站
网页制作软件名称_成立公司需要什么条件_品牌推广方案思维导图_免费独立站自建站网站

字符设备相关的知识面:已经了解了 申请设备号、注册字符设备。 已经将字符设备添加进入内核了,那么如何使用这个字符设备呢?
Linux 里面一切皆文件,对内核中的字符设备进行文件操作如打开、关闭、读、写等,但是并不支持哦。 需要相应的设备文件作为桥梁进行设备的访问,
这里需要了解知识:创建设备节点

文章目录

  • 自动创建设备节点
    • udev 知识了解
      • 动态创建设备节点
      • 自动加载驱动和触发动作
      • 支持热插拔(Hotplug)
    • 创建设备节点
      • class_create() - 创建设备类
      • device_create() - 创建设备节点
      • 销毁 class_destroy
      • 销毁 device_destroy
  • 实验
    • 源码程序 chrdev_node
      • 源码分析
    • Makefile 编译文件
    • 运行测试
      • insmod dmesg | tail
      • cat proc/devices
      • ls /sys/class/ ls /sys/class/class_test/
      • ls /dev/device_test
  • 总结


自动创建设备节点

针对手动创建设备节点,这里不概述、总结,重点是自动创建设备节点。

udev 知识了解

udev 知识了解:
在 Linux 系统中,udev(用户空间设备管理,Userspace Device Manager)是一个动态设备管理工具,负责在 /dev 目录下自动管理设备节点。它是现代 Linux 系统的核心组件,取代了传统的静态 /dev 目录管理和早期的 devfs。

udev 的核心作用:

动态创建设备节点

  • 当硬件设备插入(如 USB、硬盘、网卡等)或系统启动时,udev 会根据内核发出的 uevent 动态创建对应的设备文件(如 /dev/sda、/dev/ttyUSB0)。
  • 设备移除时,自动清理对应的设备节点。

自动加载驱动和触发动作

  • 支持在设备插入时自动加载内核模块(驱动)。
  • 触发自定义脚本(如挂载磁盘、通知用户)。

支持热插拔(Hotplug)

实时响应硬件插拔事件,适用于移动设备、外接存储等。

创建设备节点

设备文件的自动创建是利用 udev(mdev)机制来实现, 多数情况下采用自动创建设备节点
的方式。 udev(mdev)可以检测系统中硬件设备状态, 可以根据系统中硬件设备状态来创建或者
删除设备文件。 在驱动中首先使用 class_create(…)函数对 class 进行创建, 这个类存放于
/sys/class/ 目录下, 之后使用 device_create(…)函数创建相应的设备, 在进行模块加载时, 用户
空间中的 udev 会自动响应 device_create()函数, 寻找对应的类从而创建设备节点

class_create() - 创建设备类

struct class *class_create(struct module *owner, const char *name);

功能:创建一个设备类,将在/sys/class/下出现对应的目录

参数:

  • owner:struct module 结构体类型的指针, 指向函数即将创建的这个 struct class 的模块。
    一般赋值为 THIS_MODULE
  • name:类名,将出现在/sys/class/下 ;char 类型的指针, 代表即将创建的 struct class 变量的名字
  • 返回:成功返回指向class结构的指针,失败返回ERR_PTR

device_create() - 创建设备节点

struct device *device_create(struct class *cls, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...);

功能:在指定类下创建设备,触发udev在/dev下创建设备节点

参数:

  • cls:从class_create()返回的类指针 ,指定所要创建的设备所从属的类

  • parent:父设备,通常为NULL

  • devt:设备号(主设备号+次设备号)

  • drvdata:驱动私有数据,通常为NULL

  • fmt:设备名格式字符串(类似printf)

  • 返回:成功返回device指针,失败返回ERR_PTR;struct device * 类型结构体

销毁 class_destroy

用于删除设备的逻辑类, 即从 Linux 内核系统中删除设备的逻辑类。

销毁 device_destroy

extern void device_destroy(struct class *cls, dev_t devt);

用来删除 class 类中的设备属性文件, udev 会自动识别从而进行设备节点的删除。

实验

源码程序 chrdev_node


#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>static dev_t dev_num;//定义dev_t类型(32位大小)的变量dev_num
struct cdev cdev_test;  //定义struct cdev 类型结构体变量cdev_test,表示要注册的字符设备static struct file_operations cdev_test_ops = {.owner=THIS_MODULE,//将owner字段指向本模块,可以避免在模块的操作正在被使用时卸载该模块
};//定义file_operations结构体类型的变量cdev_test_opsstruct class *class_test;//定于struct class *类型结构体变量class_test,表示要创建的类static int __init chrdev_fops_init(void)//驱动入口函数
{int ret;//定义int类型的变量ret,用来判断函数返回值int major,minor;//定义int类型的主设备号major和次设备号minorret=alloc_chrdev_region(&dev_num,0,1,"chardev_num"); //通过动态方式进行设备号注册if(ret < 0){printk("alloc_chrdev_region is error\n");}   printk("alloc_chrdev_region is ok\n");major=MAJOR(dev_num);//通过MAJOR()函数进行主设备号获取minor=MINOR(dev_num);//通过MINOR()函数进行次设备号获取printk("major is %d\n",major);printk("minor is %d\n",minor);使用cdev_init()函数初始化cdev_test结构体,并链接到cdev_test_ops结构体cdev_init(&cdev_test,&cdev_test_ops);cdev_test.owner = THIS_MODULE;//将owner字段指向本模块,可以避免在模块的操作正在被使用时卸载该模块 ret= cdev_add(&cdev_test,dev_num,1);if(ret < 0 ){printk("cdev_add is error\n");}printk("cdev_add is ok\n");class_test  = class_create(THIS_MODULE,"class_test");//使用class_create进行类的创建,类名称为class_testdevice_create(class_test,NULL,dev_num,NULL,"device_test");//使用device_create进行设备的创建,设备名称为device_testreturn 0;
}
static void __exit chrdev_fops_exit(void)//驱动出口函数
{cdev_del(&cdev_test);//使用cdev_del()函数进行字符设备的删除unregister_chrdev_region(dev_num,1);//释放字符驱动设备号 device_destroy(class_test,dev_num);//删除创建的设备class_destroy(class_test);//删除创建的类printk("module exit \n");}
module_init(chrdev_fops_init);//注册入口函数
module_exit(chrdev_fops_exit);//注册出口函数
MODULE_LICENSE("GPL v2");//同意GPL开源协议
MODULE_AUTHOR("wang fang chen "); //作者信息

源码分析

使用到了前面的基础知识点

  • dev_t dev_num :设备号变量声明,dev_t 类型
  • cdev cdev_test : 字符设备结构体声明
  • file_operations cdev_test_ops :声明 定义 函数指针的集合 结构体
  • alloc_chrdev_region :动态注册设备号
  • MAJOR 、MINOR 通过设备号获取主设备号和次设备号
  • cdev_init :初始化 字符设备
  • cdev_add :字符设备添加到内核
  • class_create :进行类的创建 : 位置 /sys/class/
  • device_create :进行设备的创建,在声明 类 目录下生成device 设备,同步通过udev 机制,自动在 /dev 下生成设备节点

Makefile 编译文件


#!/bin/bash
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
obj-m += chrdev_node.o
KDIR :=/home/wfc123/Linux/rk356x_linux/kernel
PWD ?= $(shell pwd)
all:make -C $(KDIR) M=$(PWD) modulesclean:make -C $(KDIR) M=$(PWD) clean

运行测试

insmod dmesg | tail

[root@topeet:/mnt/sdcard]# insmod  chrdev_node.ko
[root@topeet:/mnt/sdcard]# dmesg | tail
[29383.739997] dwc3 fcc00000.dwc3: device reset
[29383.845540] android_work: sent uevent USB_STATE=CONNECTED
[29383.888321] configfs-gadget gadget: high-speed config #1: b
[29383.888611] android_work: sent uevent USB_STATE=CONFIGURED
[29592.130493] adbd (13142): /proc/13142/oom_adj is deprecated, please use /proc/13142/oom_score_adj instead.
[30279.336659] chrdev_node: loading out-of-tree module taints kernel.
[30279.337604] alloc_chrdev_region is ok
[30279.337626] major is 236
[30279.337643] minor is 0
[30279.337662] cdev_add is ok

程序日志,内核打印如上

cat proc/devices

结果如下,如前面 字符设备注册和设备号申请内容,说明设备已经注册到内核了。
在这里插入图片描述

ls /sys/class/ ls /sys/class/class_test/

结果如下,

  • /sys/class/ 目录下生成了class_test 类
  • /sys/class/class_test/ 目录下生成了device_test 设备

在这里插入图片描述

ls /dev/device_test

结果如下:在dev 下面生成了device_test 设备,通过udev 机制自动生成的。
在这里插入图片描述

总结

  • 字符设备知识点中的 设备节点创建内容熟悉
  • 结合以前的知识,字符设备设备号申请,字符设备注册内容进一步熟悉
  • 设备注册、类、设备创建后 在驱动卸载的时候记得 卸载

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com