自动创建字符设备驱动的设备文件

2023-11-01

目录

问题描述:

解决方案:udev(嵌入式中用的是mdev)

相关函数

在调用device_create前要先用class_create创建一个类。Linux内核中有各种类,比如gpio、rtc、led等。类这个概念在Linux中被抽象成一种设备的集合。类在/sys/class目录中。​编辑

class_create:

device_create:


问题描述:

使用mknod创建设备文件的缺点:需要手动创建与删除设备文件,那能不能自动生成设备文件呢?

解决方案:udev(嵌入式中用的是mdev)

  1. 什么是udev?应用层的一个应用程序
  2. 内核驱动和应用层udev之间有一套信息传输机制(netlink协议)
  3. 应用层启用udev,内核驱动中使用相应接口
  4. 驱动注册和注销时信息会被传给udev,由udev在应用层进行设备文件的创建和删除

注册完字符设备驱动后,添加设备类的操作,以让内核发信息给udev,让udev自动创建和删除设备文件

相关函数

  1. class_create
  2. device_create
  3. class_destroy
  4. device_destroy

在调用device_create前要先用class_create创建一个类。Linux内核中有各种类,比如gpio、rtc、led等。类这个概念在Linux中被抽象成一种设备的集合。类在/sys/class目录中。在这里插入图片描述

class_create:

#define class_create(owner, name)		\
({						\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})

class_create函数在内核中是一个宏定义。其中参数owner通常为THIS_MODULE,name为类名。

device_create:

struct device *device_create(struct class *class, struct device *parent,
			     dev_t devt, void *drvdata, const char *fmt, ...)
{
	va_list vargs;
	struct device *dev;

	va_start(vargs, fmt);
	dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
	va_end(vargs);
	return dev;
}

device_create用于创建设备。
class:该设备依附的类
parent:父设备
devt:设备号(此处的设备号为主次设备号)
drvdata:私有数据
fmt:设备名。

device_create能自动创建设备文件是依赖于udev这个应用程序。udev是一种工具,它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。

模块安装函数中:

test_class = class_create(THIS_MODULE, "aston_class");
	if (IS_ERR(test_class))
		return -EINVAL;
// 最后1个参数字符串,就是我们将来要在/dev目录下创建的设备文件的名字
// 所以我们这里要的文件名是/dev/test
device_create(test_class, NULL, mydev, NULL, "test111");

模块卸载函数中:

device_destroy(test_class, mydev);
class_destroy(test_class);

这样就可以自动进行设备文件的创建和删除了

代码范例:

#define CHRDEV_MAJOR 240  // 主设备号
#define CHRDEV_MAION 0    // 次设备号
#define CHRDEV_COUNT 1    // 次设备号个数
#define CHRDEV_NAME  "testchrdev"

struct led_cdev
{
	struct cdev chrdevcdev;
	int major;
	dev_t dev;
	struct class *led_dev_class;
};
static struct led_cdev leddev;



ssize_t chrdev_read (struct file *file, char __user *usr, size_t size, loff_t *loff)
{
	printk("%s\r\n",__func__);
	return 0;
}
int chrdev_open (struct inode *inode, struct file *file)
{
	printk("%s\r\n",__func__);
	return 0;
}
int chrdev_release (struct inode *inode, struct file *file)
{
	printk("%s\r\n",__func__);
	return 0;
}
struct file_operations fops = 
{
	.open    = chrdev_open,
	.read    = chrdev_read,
	.release = chrdev_release,
};


static int __init chrdev_init(void)
{
	int ret = 0,error = 0;
	struct device *devices;
	error = alloc_chrdev_region(&leddev.dev,CHRDEV_MAION,CHRDEV_COUNT,CHRDEV_NAME); // 注册设备号
	printk("MAJOR = %d MINOR = %d\r\n",MAJOR(leddev.dev),MINOR(leddev.dev));
	if(error < 0){
		printk("alloc_chrdev_region error\r\n");
		ret =  -EBUSY;
		goto fail;
	}
	leddev.major = MAJOR(leddev.dev);
	cdev_init(&leddev.chrdevcdev, &fops); // 绑定字符设备操作函数集
	error = cdev_add(&leddev.chrdevcdev,leddev.dev,CHRDEV_COUNT);   // 添加字符设备
	if(error < 0){
		printk("cdev_add error\r\n");
		ret =  -EBUSY;
		goto fail1;
	}
	
	// 创建类,类名为testledclass
	leddev.led_dev_class = class_create(THIS_MODULE, "testledclass");
	if (IS_ERR(leddev.led_dev_class)){
		printk("class_create error\r\n");
		ret =  -EBUSY;
		goto fail2;
	}
		
	// 创建设备
	devices = device_create(leddev.led_dev_class, NULL, MKDEV(leddev.major,0), NULL, "testled");
	if(NULL == devices){
		printk("device_create error\r\n");
		ret =  -EBUSY;
		goto fail3;
	}
	return 0;
fail3:	
	class_destroy(leddev.led_dev_class);/*  删除类 */
	
fail2:	
	cdev_del(&leddev.chrdevcdev);/*  删除cdev */
fail1:
	unregister_chrdev_region(leddev.dev,CHRDEV_COUNT);
fail:
	return ret;
}


static void __exit chrdev_exit(void)
{
	device_destroy(leddev.led_dev_class,MKDEV(leddev.major,0));/*  卸载设备 */
	class_destroy(leddev.led_dev_class);/*  删除类 */
	cdev_del(&leddev.chrdevcdev);/*  删除cdev */
	unregister_chrdev_region(leddev.dev,CHRDEV_COUNT);
}

module_init(chrdev_init);
module_exit(chrdev_exit);

MODULE_DESCRIPTION("xxxxxx");
MODULE_AUTHOR("xxxxxx");
MODULE_LICENSE("GPL");

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

自动创建字符设备驱动的设备文件 的相关文章

  • vmsplice() 和 TCP

    在原来的vmsplice 执行 有人建议 http lwn net Articles 181169 如果您的用户态缓冲区是管道中可容纳的最大页面数的 2 倍 则缓冲区后半部分成功的 vmsplice 将保证内核使用缓冲区的前半部分完成 但事
  • ALSA:snd_pcm_writei 调用时缓冲区不足

    当运行我最近从灰烬中带回来的旧程序时 我遇到了缓冲区不足的情况 该程序将原始声音文件完全加载到内存中 2100 字节长 525 帧 并准备 ALSA 进行输出 44 1khz 2 通道 有符号 16 位 if err snd pcm set
  • Google BQ:运行参数化查询,其中参数变量是 BQ 表目标

    我正在尝试从 Linux 命令行为 BQ 表目标运行 SQL 此 SQL 脚本将用于多个日期 客户端和 BQ 表目标 因此这需要在我的 BQ API 命令行调用中使用参数 标志 parameter 现在 我已经点击此链接来了解参数化查询 h
  • 我们真的应该使用 Chef 来管理 sudoers 文件吗?

    这是我的问题 我担心如果 Chef 破坏了 sudoers 文件中的某些内容 可能是 Chef 用户错误地使用了说明书 那么服务器将完全无法访问 我讨厌我们完全失去客户的生产服务器 因为我们弄乱了 sudoers 文件并且无法再通过 ssh
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 在centos中安装sqlite3 dev和其他包

    我正在尝试使用 cpanel 在 centos 机器上安装 sqlite dev 和其他库 以便能够编译应用程序 我对 debian 比 centos 更熟悉 我知道我需要的库是 libsqlite3 dev libkrb5 dev lib
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • C 语言的符号表

    我目前正在开发一种执行模式匹配的静态分析工具 我在用Flex https github com westes flex生成词法分析器 我编写了代码来管理符号表 我不太有经验C 所以我决定将符号表实现为线性链表 include
  • 使用循环在 C 中管道传输两个或多个 shell 命令

    我正在尝试执行ls wc l通过 C 语言程序 而不是使用命令行 这是我当前的工作代码 int main int pfds 2 pipe pfds pid t pid fork if pid 0 The child process clos
  • 并行运行 shell 脚本

    我有一个 shell 脚本 打乱大型文本文件 600 万行和 6 列 根据第一列对文件进行排序 输出 1000 个文件 所以伪代码看起来像这样 file1 sh bin bash for i in seq 1 1000 do Generat
  • 从 Xlib 转换为 xcb

    我目前正在将我的一个应用程序从 Xlib 移植到 libxcb 但在查找有关我有时使用的 XInput2 扩展的信息时遇到了一些麻烦 libxcb 中有 XInput2 实现吗 如果是的话 在哪里可以找到文档 目前我在使用此功能时遇到问题
  • Intel 上的 gcc 中的 _mm_pause 用法

    我参考过这个网页 https software intel com en us articles benefitting power and performance sleep loops https software intel com
  • 在生产服务器上使用 Subversion 使文件生效的最佳方法是什么?

    目前我已经设置了 subversion 这样当我在 Eclipse PDT 中进行更改时 我可以提交更改 它们将保存在 home administrator 中项目文件 该文件具有 subversion 推荐的 branches tags
  • 如何查找哪个 Yocto 项目配方填充图像根文件系统上的特定文件

    我经常与 Yocto 项目合作 一个常见的挑战是确定文件为何 或来自什么配方 包含在 rootfs 中 这有望从构建系统的环境 日志和元数据中得出 理想情况下 一组命令将允许将文件链接回源 即配方 我通常的策略是对元数据执行搜索 例如gre
  • Linux 为一组进程保留一个处理器(动态)

    有没有办法将处理器排除在正常调度之外 也就是说 使用sched setaffinity我可以指示线程应该在哪个处理器上运行 但我正在寻找相反的情况 也就是说 我想从正常调度中排除给定的处理器 以便只有已明确调度的进程才能在那里运行 我还知道
  • 检查已安装的软件包,如果没有找到则安装

    我需要检查已安装的软件包 如果未安装则安装它们 RHEL CentOS Fedora 示例 rpm qa grep glibc static glibc static 2 12 1 80 el6 3 5 i686 如何在 BASH 中进行检
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • ansible unarchive 模块如何查找 tar 二进制文件?

    我正在尝试执行一个 ansible 剧本 该剧本的任务是利用unarchive模块 因为我是在 OSX 上执行此操作 所以我需要使用它gnu tar 而不是bsd tar通常与 OSX 一起提供 因为BSD tar 不受官方支持 https
  • 无法显示 Laravel 欢迎页面

    我的服务器位于 DigitalOcean 云上 我正在使用 Ubuntu 和 Apache Web 服务器 我的家用计算机运行的是 Windows 7 我使用 putty 作为终端 遵循所有指示https laracasts com ser

随机推荐

  • function/bind的救赎(上)

    本文转自孟岩的博客 http blog csdn net myan article details 5928531 这是那篇C 0X的正文 太长 先写上半部分发了 Function bind可以是一个很简单的话题 因为它其实不过就是一个泛型
  • linux查看进程 显示,Linux如何查看和控制进程

    Linux如何查看和控制进程 前言 程序是保存在外部存储介质 如硬盘 中的可执行机器代码和数据的静态集合 而进程是在CPU及内存中处于动态执行状态的计算机程序 在Linux系统中 每个程序启动后可以创建一个或多个进程 例如 提供Web服务的
  • 等高线种类及特点

    地形图上的等高城分为首曲线 计曲线 间曲线和助曲线四种 见下图 首曲线 又叫基本等高线 是按规定的等高距 由平均海水面起算而测绘的细实线 线粗0 1毫米 用以显示地貌的基本形态 计曲线 又叫加粗等高线 规定从高程起算面 平均海水面 起算的首
  • 一个月,英语能提高多少?附资料分享

    学习语言是一个漫长的过程 但对于我这样一个英语小白 利用业余时间 一个月的学习 还是能看到不少的进步 除了听 说 读 写等能力方面有提升之外 最大的收获就是培养了英语学习和运用的兴趣 这样的结果对我来说 还是很满意的 自然也多了继续探索英语
  • STM32CubeMX代码生成和点亮LED

    所需工具STM32CubeMX和Keil5 1 先打开STM32CubeMX软件 点击New Project新建工程 2 在搜索框中搜索你的项目芯片 3 搜索出来有两个不同封装的芯片 写程序没区别 但是这个软件可以生成IO说明文档 可能会导
  • 【恒指早盘分析】10.8恒指今日复盘及后市思路

    10月8日消息 美股周一震荡收跌 市场正关注国际贸易局势的进展 美联储官员讲话以及经济数据 今日开盘 港股恒指高开0 11 随后一度涨逾1 重返26000点 截至午间收盘 恒生指数踏浪点神 1376338 669 73 46 0 28 涨0
  • justify-content、align-content、align-items、align-self的区别

    提示 CSS flex direction属性指定了内部元素是如何在 flex 容器中布局的 定义了主轴的方向 正方向或反方向 默认主轴为正方向 侧轴 与主轴垂直的轴叫侧轴 justify 使齐行 align 排列 使成一条直线 wrap
  • VBJSON报错:缺少:语句结束

    项目中使用JSON库VBJSON时报错 编译错误 缺少 语句结束 cJSONScript和cStringBuilder报相同的错误 都在第一行 VERSION 1 0 CLASS 研究了半天没啥结果 之前使用这个库的时候没有什么问题 所以判
  • Spring boot踩坑日记——ERROR c.n.d.s.t.d.RedirectingEurekaHttpClient - Request execution error

    eureka启动报错 2018 12 21 17 20 16 480 main ERROR c n d s t d RedirectingEurekaHttpClient Request execution error com sun je
  • https://github.com/qiangqiang666/demo

  • Apache Log4j2远程代码执行漏洞复现(CVE-2021-44228)-----记第一次反弹shell

    目录 靶场搭建 漏洞测试 漏洞利用 总结 靶场搭建 因为没有服务器所以只能在本地搭建 在虚拟机上拉取文件 git clone https github com vulhub vulhub git Vulhub Docker Compose
  • MariaDB安装教程

    注 从MariaDB 10 4 3开始 不再提供预构建的数据目录 并且用户需要运行mysql install db exe来创建数据目录 1 解压到自定义路径 E MariaDB mariadb 10 5 4 winx64 2 将其中的bi
  • java 类之间相互引用实例探索

    本文记录一下自己对类之间相互引用的探索 如有错误 希望不吝赐教 问题一 类之间相互引用依赖会不会引用死循环 不会 例如 A类中声明一个B类的引用 B类中也声明一个A类的引用 因为类之间的引用相当于指针 声明的时候不会分配对象 即使你在A构造
  • Windows下使用Redis(一)安装使用

    一 Redis 是什么 Redis 是一款依据BSD开源协议发行的高性能Key Value存储系统 cache and store 它通常被称为数据结构服务器 因为值 value 可以是 字符串 String 哈希 Map 列表 list
  • Error creating bean with name 'sessionFactory' defined in class path resource [...]

    已解决 spring hibernate 报错原因 applicationContext xml中没有引入实体映射文件 实体映射文件
  • 文盘 Rust -- tonic-Rust grpc 初体验

    gRPC 是开发中常用的开源高性能远程过程调用 RPC 框架 tonic 是基于 HTTP 2 的 gRPC 实现 专注于高性能 互操作性和灵活性 该库的创建是为了对 async await 提供一流的支持 并充当用 Rust 编写的生产系
  • Ceph运维存储 命令管理操作

    分布式存储运维操作 集群服务管理常用命令 统一节点上的ceph conf文件 将admin节点上修改的ceph conf 推送给所有其他节点 overwrite conf强制覆盖 ceph deploy overwrite conf con
  • C++常用头文件小结

    标准 C include
  • spring cloud 大大大大的坑。 Failed to start bean 'eurekaAutoServiceRegistration'

    先说明一下问题 我在做cloud 消费服务的时候 不是我做的我负责改而已 因我们boot 用的是1 5 4的发行版本 然后 cloud和boot的版本不一样又引入了解决的包 最后被我改回来 导致不能启动 在spring boot 中直接启动
  • 自动创建字符设备驱动的设备文件

    目录 问题描述 解决方案 udev 嵌入式中用的是mdev 相关函数 在调用device create前要先用class create创建一个类 Linux内核中有各种类 比如gpio rtc led等 类这个概念在Linux中被抽象成一种