linux下字符设备驱动的三种创建方式

Linux驱动入门(一)字符设备驱动基础 Linux驱动入门(一)字符设备驱动基础 Linux驱动入门系列 Linux驱动入门(一)字符设备驱动基础 Linux驱动入门(二)Led驱动 Linux驱动入门(三)轮询实现按键驱动 Linux驱动入门(四)中断实现按键驱动 Linux驱动入门(五)poll机制实现按键驱动 Linux驱动入门(六)使用定时器防按键抖动 文章目录Linux驱动入门(一)字符设备驱动基础一、驱动简介二、字符设备驱动... 阅读详情

第一种:作为混杂设备驱动

/*
register globalmem as a miscdevice
*/
#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<linux/sched.h>

#include<linux/miscdevice.h>
#include<linux/string.h>
#include<linux/errno.h>

#include<linux/types.h>
#include<linux/slab.h>

#include<asm/uaccess.h>

#define GLOBALMEM_SIZE 0x1000

#define DEVICE_NAME "globalmem_misc"

//create a struct for globalmem
struct globalmem_dev {
	unsigned char mem[GLOBALMEM_SIZE];
};

struct globalmem_dev *globalmem_devp;


int globalmem_open(struct inode *inode, struct file *filp)
{
	filp->private_data = globalmem_devp; //storing the globalmem to the private_data of file struct
	return 0;
}

int globalmem_release(struct inode *inode, struct file *filp)
{
	return 0;
}

static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
	unsigned long p = *ppos;
	unsigned int count = size;
	int ret = 0;
	
	struct globalmem_dev *dev = filp->private_data;//get globalmem_dev from file struct
	
	if (p >= GLOBALMEM_SIZE)
		return 0;
	if (count > GLOBALMEM_SIZE - p)
		count = GLOBALMEM_SIZE - p;
	
	if (copy_to_user(buf, (void*)(dev->mem + p), count))
		ret = -EFAULT;
	else {
		*ppos += count;
		ret = count;
		
		printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);
	}
	
	return ret;
}

static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
	unsigned long p = *ppos;
	unsigned int count = size;
	int ret = 0;
	
	struct globalmem_dev *dev = filp->private_data;
	
	if (p >= GLOBALMEM_SIZE)
		return 0;
	if (count > GLOBALMEM_SIZE - p)
		count = GLOBALMEM_SIZE - p;
		
	if (copy_from_user(dev->mem + p, buf, count))
		ret = -EFAULT;
	else {
		*ppos += count;
		ret = count;
		
		printk(KERN_INFO "written %d butes(s) from %d \n", count, p);
	}
	
	return ret;
}

static const struct file_operations globalmem_fops = {
	.owner = THIS_MODULE,
	.read = globalmem_read,
	.write = globalmem_write,
	.open = globalmem_open,
	.release = globalmem_release,
};

//miscdevice struct
static struct miscdevice misc = 
{
	.minor = MISC_DYNAMIC_MINOR,//allocate minor device number automatically,major number of msicdevice is 10
	.name = DEVICE_NAME,
	.fops = &globalmem_fops,
};

int globalmem_init(void)
{
	int result;
	result = misc_register(&misc);//register a miscdevice
	if (result)
		return result;
		
	globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
	if (!globalmem_devp) {
		result = -ENOMEM;
		goto fail_malloc;
	}
	
	memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
		
	return 0;
fail_malloc:
	misc_deregister(&misc);
	return result;
}

void globalmem_exit(void)
{
	kfree(globalmem_devp);
	misc_deregister(&misc);//deregister miscdevice
}

module_init(globalmem_init);
module_exit(globalmem_exit);

MODULE_LICENSE("GPL");

第二种:使用class_create和device_create

#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<linux/sched.h>

#include<linux/device.h>
#include<linux/string.h>
#include<linux/errno.h>

#include<linux/types.h>
#include<linux/slab.h>

#include<asm/uaccess.h>

#define GLOBALMEM_SIZE 0x1000

#define DEVICE_NAME "globalmem_class"

unsigned char globalmem_major;

static struct class *mem_class;

struct globalmem_dev {
	unsigned char mem[GLOBALMEM_SIZE];
};

struct globalmem_dev *globalmem_devp;

int globalmem_open(struct inode *inode, struct file *filp)
{
       ···
}

int globalmem_release(struct inode *inode, struct file *filp)
{
       ···
}

static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
       ···
}

static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
       ···
}

static const struct file_operations globalmem_fops = {
       ···
};

int globalmem_init(void)
{
	globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
	if (!globalmem_devp)
		return -1;
	
	memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
	
	//the first parameter 0 means allocate major device number automatically
	globalmem_major = register_chrdev(0,DEVICE_NAME,&globalmem_fops);
	if (globalmem_major < 0) 
		return globalmem_major;
	
	//create a globalmem class
	mem_class = class_create(THIS_MODULE,DEVICE_NAME);
	if (IS_ERR(mem_class))
		return -1;

	//create a globalmem device from this class
	device_create(mem_class,NULL,MKDEV(globalmem_major,0),NULL,DEVICE_NAME);
		
	return 0;
}

void globalmem_exit(void)
{
	unregister_chrdev(globalmem_major,DEVICE_NAME);//release major device number
	device_destroy(mem_class,MKDEV(globalmem_major,0));//destroy globalmem device
	class_destroy(mem_class);//destroy globalmem class
}

module_init(globalmem_init);
module_exit(globalmem_exit);

MODULE_LICENSE("GPL");

第三种:使用cdev结构体

/*
If we use cdev to register globalmem driver,we need to use command "mknod /dev/globalmem_cdev c 244 0" 
to create a device node (postulate 244 is the major device number of globalmem).
*/

#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<linux/sched.h>

#include<linux/cdev.h>
#include<linux/string.h>
#include<linux/errno.h>

#include<linux/types.h>
#include<linux/slab.h>

#include<asm/uaccess.h>

#define GLOBALMEM_SIZE 0x1000
#define MEM_CLEAR 0x1
#define GLOBALMEM_MAJOR 0


static int globalmem_major = GLOBALMEM_MAJOR;

struct globalmem_dev {
	struct cdev cdev;
	unsigned char mem[GLOBALMEM_SIZE];
};

struct globalmem_dev *globalmem_devp;


int globalmem_open(struct inode *inode, struct file *filp)
{
       ···
}

int globalmem_release(struct inode *inode, struct file *filp)
{
       ···
}

static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
       ···
}

static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
       ···
}

static const struct file_operations globalmem_fops = {
       ···
};

static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)
{
	int err, devno = MKDEV(globalmem_major, 0);
	
	cdev_init(&dev->cdev, &globalmem_fops);//initialize cdev
	dev->cdev.owner = THIS_MODULE;
	err = cdev_add(&dev->cdev, devno, 1);//add cdev to system
	if (err)
		printk(KERN_NOTICE "Error %d adding globalmem %d", err, index);
}

int globalmem_init(void)
{
	int result;
	
	globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);//allocate memory for globalmem_devp
	if (!globalmem_devp) {
		result = -ENOMEM;
		return result;
	}
	
	memset(globalmem_devp, 0, sizeof(struct globalmem_dev));//initialize globalmem_devp
	
	dev_t devno = MKDEV(globalmem_major, 0);//create a device number
	
	if (globalmem_major)
	    result = register_chrdev_region(devno, 1, "globalmem_cdev");//request device number
	else {
		result = alloc_chrdev_region(&devno, 0, 1, "globalmem_cdev");//request device number automatically
		globalmem_major = MAJOR(devno);
	}
	
	if (result < 0)
		return result;
		
	globalmem_setup_cdev(globalmem_devp, 0);
	return 0;
}

void globalmem_exit(void)
{
	cdev_del(&globalmem_devp->cdev);//delete cdev from system
	kfree(globalmem_devp);
	unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);//release device number
}

module_init(globalmem_init);
module_exit(globalmem_exit);

MODULE_LICENSE("GPL");




Linux 字符设备驱动结构—— cdev 结构体、设备号相关知识解析及创建字符设备示例 一、字符设备基础知识 1、设备驱动分类 linux系统将设备分为3类:字符设备、块设备、网络设备。使用驱动程序的方式如下: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据。字符设备是面向流的设备,常见的字符设备有鼠标、键盘、串口、控制台和LED设备等。 块设备:是指可以从设备的任意位置读取一定长度数据的设备。块设备包括硬盘、磁盘、U盘和SD卡等。 每一个字符设备或块设备都在/dev目录下对应一个设备文件。lin... 阅读详情

相关推荐

深入理解Linux字符设备驱动

文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次、组成框架和交互、如何编写驱动、设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解。

嵌入式企鹅圈 7818

Linux设备驱动-创建字符设备

字符设备驱动程序,内容主要包括初始化、添加、删除cedv,申请和释放设备号,以及填充file_operations的操作函数

Leo-夜空的博客 768

Linux驱动开发——新字符设备驱动开发

之前的字符设备驱动,使用register_chrdev函数注册设备,使用的时候需要mknod命令创建设备节点。register_chrdev和unregister_chrdev是老版本的驱动使用的函数,新的字符设备驱动已经不再使用,而是使用Linux内核推荐的新字符设备驱动API函数。

一切皆是定数的博客 1418

[Linux驱动开发二]最简单的字符设备

一个最简单的字符设备

weixin_42857944的博客 2405

linux驱动开发proc文件初步

proc文件系统讲解,非常详细。 1 收集系统信息 1.0 proc文件系统概览 1.1 进程相关信息子目录 1.2 内核数据 1.3 IDE接口信息 /proc/ide 1.4 网络统计信息 /proc/net 1.5 SCSI接口信息 /proc/scsi 1.6 并行端口信息 /proc/parport 1.7 TTY端口信息 /proc/tty 2 调整内核参数 2.1 /proc/sys/fs - 文件系统数据 2.2 /proc/sys/fs/binfmt_misc - 二进制可执行格式杂项 2.3 /proc/sys/kernel - 通用系统参数 2.4 /proc/sys/vm - 虚拟内存系统 2.5 /proc/sys/dev - 设备相关参数 2.6 /proc/sys/sunrpc - 远程过程调用 2.7 /proc/sys/net - 网络子系统可调参数 2.8 /proc/sys/net/ipv4 - IPV4设置 2.9 Appletalk 2.10 IPX

基于Coze平台从零构建AI智能体:以测试用例生成为例的实战指南

在人工智能技术快速发展的今天,大语言模型(LLM)和提示词工程(Prompt Engineering)已成为构建智能应用的核心技术。其原理在于通过自然语言指令引导模型完成特定任务,其技术价值在于极大地降低了AI应用开发的门槛,使非专业开发者也能快速实现想法。这一技术广泛应用于自动化办公、智能客服、内容生成等场景。本文聚焦于字节跳动旗下的Coze平台,该平台通过可视化工作流编排和预置技能,将上述技术封装为易用的工具。文章以“根据产品需求文档(PRD)自动生成测试用例”这一具体场景为例,详细拆解了从需求分析、工

weixin_30617695的博客 337

(Linux驱动入门)字符设备

内核中通过类型dev_t来描述设备号,其实质是unsigned int 32位整数,其中。这是Linux内核中注册字符设备驱动的函数之一,它的作用是在内核中申请一段设备号,并将其与设备驱动程序进行绑定。fromcountname函数执行成功时,会返回0,否则返回一个负数错误码。

qq_57594025的博客 789

FastAPI + Layui:打造企业级敏捷开发后台管理系统

本文详细介绍了如何使用FastAPI和Layui构建高效的企业级后台管理系统。FastAPI提供高性能的异步API支持,而Layui则简化了前端开发流程,两者结合可实现快速开发和部署。文章涵盖了从环境搭建、核心组件开发到性能优化的全流程,特别适合需要敏捷开发的企业项目。

weixin_29045585的博客 555

Linux 字符设备驱动结构(二)—— 自动创建设备节点

自动创建设备节点 device_create与class_create函数的使用

发如雪 1198

米哈游 AI产品经理面试题精选:10道高频考题+答案解析(附PDF)

米哈游是全球知名游戏开发商,以《原神》《崩坏》系列著称,专注二次元文化与AI技术创新。本文整理了10道AI产品经理面试题,涵盖Transformer架构、智能NPC设计、机器学习应用、AIGC产品规划等核心领域。题目既考察技术理解(如RAG原理、多模态模型),又关注产品落地(游戏平衡性优化、伦理安全),同时强调跨团队协作能力。参考答案均结合米哈游业务场景,体现技术驱动与玩家体验并重的产品思维,展现AI在游戏行业的创新应用前景。

ZHHHHH15的博客 679

快速了解Spyder

一 面板介绍菜单栏:放置所有功能工具栏:放置快捷菜单,可以通过菜单栏中的View的Toolbars的复选框来勾选工作区:写代码的地方属性页的标题栏:可以显示当前代码的名字和位置查看栏:查看文件、调试时的对象及变量输出栏:查看程序的输出信息,也可以作为shell终端来输入Python语句状态栏:用来显示当前文件权限、编码,光标指向位置和系统内存二 注释功能注释功能为编写代码很常用功能,下面介绍Spy...

实践求真知 1万+

[Linux内核驱动]创建字符设备

创建一个简单的字符设备

qq_66623299的博客 980

从0开始,部署micro_ros+stm32f407+stm32cubeIDE

(5)安装依赖项rosdep时,必须处于创建的microros_ws中,因为里面有clone的src文件夹。(3)教程a中的安装docker不是必须的,取决于运行agent时是否想使用docker。(4)记得安装rosdep,并在以后的命令中将rosdep替换为rosdepc。4、运行agent,选择udp、tcp、can、串口,这里没有使用docker。(1)首先参考教程a安装虚拟机和ubuntu,注意版本选择22.04;(2)参考教程b部署micro_ros构建系统。二、安装和运行agent。

m0_37963053的博客 2234

有linux下的字符设备驱动程序,linux下字符设备驱动的三种创建方式

第一种:作为混杂设备驱动/*register globalmem as a miscdevice*/#include#include#include#include#include#include#include#include#include#include#define GLOBALMEM_SIZE 0x1000#define DEVICE_NAME "globalmem_misc"//cre...

weixin_30402009的博客 127

关于三维全波电磁场仿真软件CST的安装和问题解决

百度网盘链接:https://pan.baidu.com/s/1RgWr8Qau1EzSOlh29SewFQ提取码:fzza这里是2023版本的CST,需要其他版本的uu们可以去官网或者其他人的网盘下载。

weixin_60728441的博客 3604

迫零均衡前与迫零均衡后眼图对比附Matlab代码

迫零均衡(Decision Feedback Equalization,DFE)是一种常用的数字通信技术,用于抑制信号传输中的多径干扰。迫零均衡(Decision Feedback Equalization,DFE)是一种常用的数字通信技术,用于抑制信号传输中的多径干扰。眼图是一种常用的信号质量评估工具,通过绘制接收到的信号在时域上的波形,可以直观地观察到噪声、失真和干扰等问题。眼图是一种常用的信号质量评估工具,通过绘制接收到的信号在时域上的波形,可以直观地观察到噪声、失真和干扰等问题。

ByteSparkX的博客 459

linux 驱动 节点随便目录,驱动三种字符注册设备节点的方法

字符设备注册:杂项设备注册方法、早期经典方式注册方法、linux2.6版本注册方法区别:安装杂项设备会在/dev目录生成设备文件,早期经典标准字符设备驱动模型和linux2.6标准字符设备驱动不会自动生成设备文件。杂项设备:Linux杂项驱动出现的意义在于:有很多简单的外围字符设备,它们功能相对简单,一个设备占用一个主设备号对于内核资源来说太浪费。所以对于这些简单的字符设备它们共用一个主设备号,不...

weixin_42171208的博客 490

2024 年高教社杯全国大学生数学建模竞赛 E 题 交通流量管控 详细思路+matlab代码+python代码+论文范例

随着城市化进程的加快、机动车的快速普及,以及人们活动范围的不断扩大,城市道。景区周边道路上既有本地居民出行,也有过境车辆,化配置,在保证车辆通行的前提下,使得两条主路上的车流平均速度最大。对五一黄金周期间的数据进行分析,判定寻找停车位的巡游车辆,并估算假。相位通过的每辆车的信息,包括拍摄地点、行驶方向、拍摄时间和车牌号。济发展和百姓幸福感的一个“痛点”,是相关部门的棘手难题之一。纬中路交叉口,根据车流量的差异,可将一天分成若干个时段,估。是小镇中两条主路的情况:纬中路,从环西路到环东路,约。

YOLO 3310

字符设备驱动

一. 知识点 1. 设备号; 2. 创建设备文件; 3. 设备注册; 4. 重要数据结构; 5. 设备操作; 二.主设备号 字符设备通过字符设备文件来存取。字符设备文件由使用ls -l 的输出的第一列的”C”标识; 如果使用ls –l 命令,会看到在设备文件项中有2个数(由一个逗号分隔)这些数字就是设备文件的主次设备编 举例: crw-rw---- 1 ro...

java开发指南博客 【转载】 202

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

linux 设备节点 驱动,linux driver ------ 字符设备驱动 之 “ 创建设备节点流程 ”...

在字符设备驱动开发的入门教程中,最常见的就是用device_create()函数来创建设备节点了,但是在之后阅读内核源码的过程中却很少见device_create()的踪影了,取而代之的是device_register()与device_add(),将device_create()函数展开不难发现:其实device_create()只是device_register()的封装,而device_re...

weixin_39776344的博客 272

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Linux驱动开发 2 - 从零实现内核模块

本文介绍如何创建一个简单的Linux字符设备驱动,并提供了一个完整的misc设备驱动示例

u014034516的博客 1019

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Linux内核驱动自动创建设备节点文件

Linux内核驱动自动创建设备节点文件 (2012-06-16 10:06) 标签:  转载  原文地址:Linux内核驱动自动创建设备节点文件 作者:xgqsa Linux下生成驱动设备节点文件的方法有3个:1、手动mknod;2、利用devfs;3、利用udev 在刚开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点,实际上Lin

ganjianfeng2003的专栏 640

Linux之字符设备驱动框架

Linux驱动属于内核的一部分,学习驱动开发时将驱动设计为内核模块,内核模块是一种可以在系统运行时加载和卸载的机制。内核编程的注意事项1.不能使用C标准库和C标准头文件2.使用GNU C3.没有内存保护机制4.不能处理浮点运算5.注意并发互斥和可移植性问题1.内核模块Linux 驱动有两种运行方式,第一种是将驱动编译进 Linux 内核中,当 Linux 内核启动的时就会自动运行驱动程序。第二种是将驱动编译成模块(Linux 下模块扩展名为.ko),在Linux 内核启动以后。

风间琉璃的博客 5892

【Linux 驱动篇(一)】字符设备驱动开发

字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的点灯、按键、 IIC、 SPI,LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。

K3169的博客 5665

Linux字符设备驱动详解

前言 很久没有认真写一篇博客了,刚好最近学习了Linux字符设备驱动,好记心不如烂笔头,当然是要抓紧记下来,在开始之前安利一个师弟写的几篇博客,写得很不错。本文主要来自正点原子、野火Linux教程及本人理解,若有侵权请及时联系本人删除。 从单片机到ARM Linux驱动——Linux驱动入门篇 Linux字符设备驱动开发(2)——让开发板上的灯闪烁 正文 Linux内核是怎么设计字符设备 结合前两篇文章,我这里讲的就比较简洁,下图是字符设备的整体框图。将其分为三步。 第一步:填充并保存硬件接口 这一步就是

weixin_45905650的博客 6790

Linux驱动device_create创建字符设备文件

在Linux中有两种创建字符设备的方法,一种是通过mknod手动进行设备文件创建,第二种是通过device_create函数进行设备文件创建。在驱动开发中常用第二种方式进行设备文件的创建。 class_create和device_create 先来了解一下跟设备文件创建相关的两个函数。 class_create:在调用device_create前要先用class_create创建一个类。类这个概念在Linux中被抽象成一种设备的集合。类在/sys/class目录中。 Linux内核中有各种类,比如gpi

hwx1546的博客 1万+
上一篇: linux下devicetree中常用的of函数
下一篇: linux驱动中的链表操作
EmSoftEn
博客等级 码龄12年 40粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值