5、注册字符类设备

字符设备

cdev结构体

Linux中使用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;
}

字符设备相关函数

使用 cdev_init 函数初始化 cdev结构体,成员变量,建立cdev 和file_operations 之间的联系

使用cdev_add 函数向系统添加一个cdv结构体,也就是添加一个字符设备。

使用cdev_delete函数删除一个字符设备;

file_operations结构体:

对设备节点进行文件操作时,最终会调用 设备驱动里的 file_operations 结构体里的文件操作函数:

例如:open、 release、read、write、ioctl、prode;

file_operations 结构体定义在include/linux/fs.h文件中

一个简化的 file_operations 结构体的定义示例:

struct file_operations {  struct module *owner;  loff_t (*llseek) (struct file *, loff_t, int);  ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);  ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);  ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);  ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);  int (*iterate) (struct file *, struct dir_context *);  unsigned int (*poll) (struct file *, struct poll_table_struct *);  long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);  long (*compat_ioctl) (struct file *, unsigned int, unsigned long);  int (*mmap) (struct file *, struct vm_area_struct *);  int (*open) (struct inode *, struct file *);  int (*flush) (struct file *, fl_owner_t id);  int (*release) (struct inode *, struct file *);  int (*fsync) (struct file *, loff_t, loff_t, int datasync);  int (*fasync) (int, struct file *, int);  int (*lock) (struct file *, int, struct file_lock *);  ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);  unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);  int (*check_flags)(int);  int (*flock) (struct file *, int, struct file_lock *);  ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);  ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);  int (*setlease)(struct file *, long, struct file_lock **);  long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len);  void (*show_fdinfo)(struct seq_file *m, struct file *f);  #ifdef CONFIG_AIO  ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);  ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);  int (*aio_fsync) (struct kiocb *, int datasync);  #endif  /* ... 其他可能的成员函数 ... */  
};

设备节点

每个设备在Linux系统中都有一个设备文件,这个设备文件就是通常所说的设备节点,应用程序通过操作这个设备文件,便可以操作相对应的硬件;

设备节点创建在、dev目录下;

创建设备节点的方式

      1、手动创建

     

  mknod  /dev/test c 236 0

2、函数中自动创建

        可以通过mdev机制自动创建

udev机制:

        Linux中通过udev来实现设备节点的创建和删除,udev是一个用户程序,可以根据系统中设备的状态来创建或者删除设备节点,比如说,如果驱动程序成功加载到Linux时,会自动在/dev目录下创建相对应的设备节点,当驱动程序卸载时,会自动删除/dev目录下的设备节点,

在嵌入式linux系统中使用mdev,mdev时udev的简化板本,在使用busybox构建根文件系统时,busybox会自动创建mdev

相关函数

 class_create函数

        函数定义在 include/linux/device.h文件当中,使用这个函数,将会在系统的/sys/class 下创建一个文件;

#include <linux/device.h>  struct class *class_create(struct module *owner, const char *name);

device_create 函数

        使用class_create 创建好类之后,还需要 device_create 函数在类下面创建一个设备。定义在include/linux/device.h文件中
 

#include <linux/device.h>  struct device *device_create(struct class *cls, struct device *parent,  dev_t devt, void *drvdata,  const char *fmt, ...);

device_destroy 函数

        删掉创建的设备

 class_destroy 函数

        删掉创建的类

内核空间和用户空间的数据交换

应用层和内核不能直接进行数据传输,可以使用 copy_from_user,copy_to_user,需要包含头文件 Linux/uaccess.h,这些函数提供了对访问违规(如地址无效或越界)的检查,从而增加了内核的稳定性。

copy_to_user

        内核空间数据copy到用户空间

#define copy_to_user(to, from, n) _copy_to_user((to), (from), (n))  

copy_from_user

        用户空间copy到内核空间

例程

#include <linux/module.h>
#include <linux/init.h>#include <linux/fs.h>
#include <linux/modulepram.h>
#include <linux/kdev_t.h>#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/asm-generic/uaccess.h>  static int major;
static int minor; module_param(major,int,S_IRUGO);
MODULE_PARAM_DESC(major,"e.g:major=1");module_param(minor,int,S_IRUGO);
MODULE_PARAM_DESC(minor,"e.g:minor=1");static struct cdev cdev_test;struct class *class;
struct device *device;static  int cdev_test_open(struct inode *node, struct file *file)
{printk("cdev_test_open \n");return 0;
}static int cdev_test_release(struct inode *node, struct file *file)
{printk("cdev_test_release \n");return 0;}static ssize_t cdev_test_read (struct file *file, char __user *buf, size_t size, loff_t *off)
{char kbuf[64]="123456hello";copy_to_user(buf,kbuf,strlen(kbuf));printk("cdev_test_read \n");}  static ssize_t cdev_test_write (struct file *file, const char __user *buf, size_t size, loff_t *off)
{char kbuf[64];copy_from_user(kbuf,buf,size);printk("write buf[%s]\n",kbuf);printk("cdev_test_write\n");}struct file_operations cdev_test_ops={.owner=THIS_MODULE,.open=cdev_test_open,.release=cdev_test_release,.read=cdev_test_read,.write=cdev_test_write,.ioctl=cdev_test_ioctl
};static int cdv_init(void)
{dev_t dev_num;int ret;printk("input major=%d minor=%d \n",major,minor);if(major == 0){//静态申请dev_num=MKDEV(major,minor);ret=register_chrdev_region(dev_num,1,"chrdev_num");if(0 != ret){printk("register_chrdev_region err %d\n",ret);return ret;}}else{//动态申请ret=alloc_chrdev_region(&dev_num,0,1,"chrdev_num");if(0 != ret){printk("alloc_chrdev_regionerr %d\n",ret);return ret;}printk("dev_num=%d \n",dev_num);major = MAJOR(dev_num);minor = MINOR(dev_num);printk("input major=%d minor=%d \n",major,minor);}cdev_test.owner= THIS_MODULE;cdev_init(&cdev_test,&&cdev_test_ops);  cdev_add(&cdev_test,dev_num,1);class = class_create(THIS_MODULE,"test");device = device_create(class,NULL,dev_num,NULL,"/dev/test");printk("cdv init\n");return 0;
}static void cdv_exit(void)
{//释放设备号unregister_chrdev_region(dev_num,1);cdev_del(&cdev_test);device_destroy(class,dev_num);classs_destroy(class);printk("cdv exit\n");return 0;
}module_init(cdv_init);
module_exit(cdv_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("SONG");
MODULE_VERSION("v1.0");

APP应用程序

app.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int arc, char *argv[])
{int fd;char buf[64]={0};fd = open("/dev/test",O_RDWR);if(fd < 0){printf("open err\n");}read(fd,buf,sizeof(buf));printf("read [%s]\n",buf);char buf1[64]="4578kkk";write(fd,buf1,strlen(buf1));close(fd);return 0;}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Java初阶数据结构》----5.<二叉树的概念及使用>

前言 大家好&#xff0c;我目前在学习java。之前也学了一段时间&#xff0c;但是没有发布博客。时间过的真的很快。我会利用好这个暑假&#xff0c;来复习之前学过的内容&#xff0c;并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区…

综合点评!史上最强开源大模型Llama 3.1

在人工智能领域&#xff0c;开源模型一直是推动技术进步和创新的重要力量。 北美时间7月23日&#xff0c;Meta公司&#xff08;原Facebook&#xff09;宣布了一项重大突破&#xff1a;开源模型Llama 3.1的正式发布。这一举措预示着AI技术的又一次飞跃&#xff0c;Llama 3.1有望…

虚拟化数据恢复—XenServer VPS不可用如何恢复数据?

虚拟化数据恢复环境&#xff1a; 某品牌R720服务器&#xff0c;4块STAT硬盘通过H710P阵列卡组建了一组raid10磁盘阵列。服务器上部署XenServer虚拟化平台&#xff0c;虚拟机安装Windows Server系统&#xff0c;作为Web服务器使用&#xff0c;运行SQL Server数据库。共有2个虚拟…

【数据结构】——堆的实现与算法

目录 一、堆的实现 1.1堆数据的插入 1.2堆数据的删除 二、建堆算法 2.1向上调整建堆 2.2向下调整建堆 三、堆的应用 3.1堆排序 3.2Top—K问题 一、堆的实现 1.1堆数据的插入 插入一个数据后不再是小堆需要将新数据调整到合适的位置&#xff0c;所以堆的插入就是在数组…

类和对象(中 )C++

默认成员函数就是用户不显示实现&#xff0c;编译器会自动实现的成员函数叫做默认成员函数。一个类&#xff0c;我们在不写的情况下&#xff0c;编译器会自动实现6个默认成员函数&#xff0c;需要注意&#xff0c;最重要的是前4个&#xff0c;其次就是C11以后还会增加两个默认成…

onlyoffice用nginx反向代理

我对于onlyoffice的需求就是当个在线编辑器使用。在集成react的时候之前都是写的绝对路径的地址&#xff0c;这样在需要迁移应用的时候就造成了巨大的麻烦&#xff0c;所以我决定用nginx做反向代理&#xff0c;这样我集成的时候就不用每次都修改源码中的地址了。 一开始写的代…

昇思25天学习打卡营第XX天|基于MindSpore通过GPT实现情感分类

其实数据集和模型的其他大平台接口的&#xff0c;感觉不用非包在自己包里 %env HF_ENDPOINThttps://hf-mirror.com mindnlp.transformers 库中的 GPTTokenizer 类来加载和处理与GPT&#xff08;生成式预训练变换器&#xff09;模型兼容的分词器&#xff0c;并添加特殊的控制标…

Spring源码(八)--Spring实例化的策略

Spring实例化的策略有几种 &#xff0c;可以看一下 InstantiationStrategy 相关的类。 UML 结构图 InstantiationStrategy的实现类有 SimpleInstantiationStrategy。 CglibSubclassingInstantiationStrategy 又继承了SimpleInstantiationStrategy。 InstantiationStrategy I…

SpringBoot通过3种方式实现AOP切面

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

Sonar-Scanner: 静态代码分析的利器

Sonar-Scanner: 静态代码分析的利器 懂得享受生活的过程&#xff0c;人生才会更有乐趣。每个人都会遇到一些陷阱&#xff0c;每个人都有过去&#xff0c;有的甚至是失败的往事。过去的错误和耻辱只能说明过去&#xff0c;真正能代表人一生的&#xff0c;是他现在和将来的作为。…

【更新2022】省级农民专业合作社数量 无缺失 2006-2022

省级农民专业合作社数量是研究中国农村经济组织和农业社会化服务的重要数据。这些数据可以用来分析不同省份农业生产组织形式的多样性及其对农民生产、技术创新和收入增长的影响。研究者可以基于这些数据&#xff0c;探讨农民专业合作社在提升农产品质量、优化农业生产结构和推…

Transformer处理文本分类实例(Pytorch)

文章目录 Transformer处理文本分类实例参考网站我们构建一个实例问题,预测AG_NEWS的文本分类AG_NEWS数据集介绍预测目标总体思路(简述)主要流程数据预处理dataset构建(不是重点)构建词表 编写处理模型执行词嵌入位置编码(PositionalEncoding)(*核心)多层Transformer模块多头自注…

Mojo数据类型详解

Mojo 中的所有值都分配有相对应的数据类型&#xff0c;大多数类型都是由结构体定义的标称的类型。这些类型是标称的&#xff08;或“命名的”&#xff09;&#xff0c;因为类型相等性是由类型的名称而不是其结构决定的。 有一些类型未定义为结构&#xff0c;例如下面的两种情况…

百款精选的HTML5小游戏源码,你可以下载并直接运行在你的小程序或者自己的网站上

今天我带来了一份特别的礼物——百款精选的HTML5小游戏源码&#xff0c;你可以下载并直接运行在你的小程序或者自己的网站上&#xff0c;只需双击index.html即可开始。无论你是在寻找创意引流&#xff0c;还是想为你的网站增添互动性&#xff0c;这些小游戏都能帮你实现&#x…

办公必备!一键把PDF转换为PPT文件,只需这3款神器!

在当今数字化办公环境中&#xff0c;文件格式的转换已成为提高工作效率的关键因素之一。其中&#xff0c;PDF(便携式文档格式)和PPT(PowerPoint演示文稿)是两种广泛使用的文件格式。然而&#xff0c;有时我们需要将PDF文件转换为PPT格式&#xff0c;以便进行编辑或演示。 为方…

数据结构的基本概念与算法

数据结构的基本概念与算法 什么是数据&#xff1f; 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符以及所有能输入到计算机中并被计算机程序识别和处理的符号的集合&#xff1b;总结来说 -> 数据就是计算机程序加工的原料&#xff1b; 数据元素、数据项&#xf…

<数据集>棉花识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;13765张 标注数量(xml文件个数)&#xff1a;13765 标注数量(txt文件个数)&#xff1a;13765 标注类别数&#xff1a;4 标注类别名称&#xff1a;[Partially opened, Fully opened boll, Defected boll, Flower] 序…

Java面试——Tomcat

优质博文&#xff1a;IT_BLOG_CN 一、Tomcat 顶层架构 Tomcat中最顶层的容器是Server&#xff0c;代表着整个服务器&#xff0c;从上图中可以看出&#xff0c;一个Server可以包含至少一个Service&#xff0c;用于具体提供服务。Service主要包含两个部分&#xff1a;Connector和…

SQL labs-SQL注入(七,sqlmap对于post传参方式的注入,2)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。参考&#xff1a;SQL注入之Header注入_sqlmap header注入-CSDN博客 序言&#xff1a; 本文主要讲解基于SQL labs靶场&#xff0c;sqlmap工具进行的post传参方式的SQL注入&#xff0c…

【Java版数据结构】初识泛型

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 br />个人主页&#xff1a;Gu Gu Study专栏&#xff1a;Java版数据结构 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1…