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

16 篇文章 0 订阅

                            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 0


MODULE_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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值