当前位置: 首页 > news >正文

ARM驱动学习之8 动态申请字符类设备号

                            ARM驱动学习之8 动态申请字符类设备号

KernelCode:
• 字符设备函数在文件“include/linux/fs.h”中
• alloc_chrdev_region() 是动态分配主次设备号。
• 宏定义MAJOR提取dev_t数据中的主设备号源码:
/*** alloc_chrdev_region() - register a range of char device numbers* @dev: output parameter for first assigned number* @baseminor: first of the requested range of minor numbers * @count: the number of minor numbers required* @name: the name of the associated device or driver** Allocates a range of char device numbers.  The major number will be* chosen dynamically, and returned (along with the first minor number)* in @dev.  Returns zero or a negative error code.*/int alloc_chrdev_region(dev_t *dev,unsigned baseminor, unsigned count,const char *name)
{struct char_device_struct *cd;cd = __register_chrdev_region(0, baseminor, count, name);if (IS_ERR(cd))return PTR_ERR(cd);*dev = MKDEV(cd->major, cd->baseminor);return 0;
}/*** unregister_chrdev_region() - return a range of device numbers* @from: the first in the range of numbers to unregister* @count: the number of device numbers to unregister** This function will unregister a range of @count device numbers,* starting with @from.  The caller should normally be the one who* allocated those numbers in the first place...*/
void unregister_chrdev_region(dev_t from, unsigned count)
{dev_t to = from + count;dev_t n, next;for (n = from; n < to; n = next) {next = MKDEV(MAJOR(n)+1, 0);if (next > to)next = to;kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));}
}1.在scdev_init如下:
DEVICE_NAME改为“ascdev”
ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);
numdev_magor = MAJOR(num_dev);
printk(KERN_EMERGE "numdev_magor is %d \n",numdev_magor);• 加载运行
– 使用命令“cat /proc/devices”查看
– 动态加载模块之后再查看设备号

源码:

#include <linux/init.h>
/*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/
#include <linux/module.h>
/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*//*定义module_param module_param_array的头文件*/
#include <linux/moduleparam.h>
/*定义module_param module_param_array中perm的头文件*/
#include <linux/stat.h>/*字符设备函数*/
#include <linux/fs.h>
/*MDKDEV转换设备号数据类型宏定义*/
#include <linux/kdev_t.h>
/*定义字符设备的结构体*/
#include <linux/cdev.h>#define DEVICE_NAME "Ascdev"
#define DEVICE_MINOR_NUM 2
#define DEV_MAJOR 0
#define DEV_MINOR 0MODULE_LICENSE("Dual BSD/GPL");
/*声明是开源的,没有内核版本限制*/
MODULE_AUTHOR("iTOPEET_dz");
/*声明作者*/static int numdev_major = DEV_MAJOR ;//主设备号
static int numdev_minor = DEV_MINOR ;//次设备号module_param(numdev_major,int,S_IRUSR);
module_param(numdev_minor,int,S_IRUSR);static int Ascdev_init(void)
{int ret = 0;dev_t num_dev;if(numdev_major){num_dev = MKDEV(numdev_major,numdev_minor);//宏命令,用于处理各种设备号相关的数据//设备注册ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME);if(ret < 0){printk(KERN_EMERG "register_chrdev_region req is %d is failed \n",num_dev );return -1;}printk(KERN_EMERG "register_chrdev_region %d is success \n",numdev_major);	}else{ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);if(ret < 0){printk(KERN_EMERG "alloc_chrdev_region req is %d is failed \n",num_dev );return -1;}numdev_major = MAJOR(num_dev);printk(KERN_EMERG "numdev_major is %d \n",numdev_major);}printk(KERN_EMERG "Ascdev enter!\n");/*打印信息,KERN_EMERG表示紧急信息*/return 0;
}static void Ascdev_exit(void)
{	unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);printk(KERN_EMERG "Ascdev exit!\n");
}module_init(Ascdev_init);
/*初始化函数*/
module_exit(Ascdev_exit);
/*卸载函数*/

Makefile:

#!/bin/bash
#通知编译器我们要编译模块的哪些源码
#这里是编译itop4412_hello.c这个文件编译成中间文件itop4412_hello.o
#obj-m += mini_linux_module.o 
obj-m += request_cdev_num.o 
#源码目录变量,这里用户需要根据实际情况选择路径
#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的
KDIR := /home/topeet/Android4.0/iTop4412_Kernel_3.0
#当前目录变量
PWD ?= $(shell pwd)#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(KDIR)Linux源码目录,作者这里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
#$(PWD)当前目录变量
#modules要执行的操作
all:make -C $(KDIR) M=$(PWD) modules#make clean执行的操作是删除后缀为o的文件
clean:rm -rf *.mod.c *.o *.order *.ko *.mod.o *.symvers

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Serverless 安全新杀器:云安全中心护航容器安全
  • string的模拟实现and友元
  • 政务安全体系构建中的挑战
  • Python的学习步骤
  • TDengine 与 SCADA 强强联合:提升工业数据管理的效率与精准
  • 物联网架构
  • steamdeck执行exe文件
  • 什么是Bean的循环依赖?解决方案是什么?
  • 基于STM32设计的水渠闸门远程控制系统(华为云IOT)(226)
  • PostgreSQL(PG)(二十二)
  • “从零到一:使用IntelliJ IDEA打造你的梦幻HTML项目“
  • 【Unity】 HTFramework框架(五十六)MarkdownText:支持运行时解析并显示Markdown文本
  • 前端 + 接口请求实现 vue 动态路由
  • QTreeView模糊查询
  • 建模杂谈系列256 规则函数化改造
  • [deviceone开发]-do_Webview的基本示例
  • angular2 简述
  • Intervention/image 图片处理扩展包的安装和使用
  • java多线程
  • js对象的深浅拷贝
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Linux下的乱码问题
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • RxJS: 简单入门
  • Shadow DOM 内部构造及如何构建独立组件
  • SQLServer之索引简介
  • Yii源码解读-服务定位器(Service Locator)
  • 对象管理器(defineProperty)学习笔记
  • 你真的知道 == 和 equals 的区别吗?
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 首页查询功能的一次实现过程
  • 探索 JS 中的模块化
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 2017年360最后一道编程题
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • 通过调用文摘列表API获取文摘
  • ​iOS实时查看App运行日志
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $forceUpdate()函数
  • (¥1011)-(一千零一拾一元整)输出
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (vue)el-tabs选中最后一项后更新数据后无法展开
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)springboot人体健康检测微信小程序 毕业设计 012142
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (佳作)两轮平衡小车(原理图、PCB、程序源码、BOM等)
  • (三)Kafka 监控之 Streams 监控(Streams Monitoring)和其他
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • ******之网络***——物理***
  • ***监测系统的构建(chkrootkit )