博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
17-18_静态和动态申请字符类设备号
阅读量:318 次
发布时间:2019-03-04

本文共 6147 字,大约阅读时间需要 20 分钟。

 

1. 相关头文件与函数

1.1 fs.h

字符设备函数在文件“include/linux/fs.h”中

内核提供了三个函数来注册一组字符设备编号,这三个函数分别是
– register_chrdev_region()
– alloc_chrdev_region()
– register_chrdev()

(1)register_chrdev_region

int register_chrdev_region(dev_t from, unsigned count, const char *name)

from :要分配的设备编号范围的初始值, 这组连续设备号的起始设备号, 相当于register_chrdev()中主设备号

Count:连续编号范围.   是这组设备号的大小(也是次设备号的个数)
Name:编号相关联的设备名称. (/proc/devices); 本组设备的驱动名称

(2)alloc_chrdev_region

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;}

dev :alloc_chrdev_region函数向内核申请下来的设备号

baseminor :次设备号的起始

count:申请次设备号的个数

name :执行 cat /proc/devices显示的名称

(3)register_chrdev(老版本的字符设备申请函数)

int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)

major: 主设备号,当用户设置为0时,内核会动态分配一个设备号。

name:设备名称
fops:文件系统的接口指针

1.2 kdev_t.h

头文件位置 “include/linux/kdev_t.h”。

#define MAJOR(dev)	((unsigned int) ((dev) >> MINORBITS))#define MINOR(dev)	((unsigned int) ((dev) & MINORMASK))#define MKDEV(ma,mi)	(((ma) << MINORBITS) | (mi))

宏定义:#define MKDEV(major,minor) (((major) << MINORBITS) | (minor))

major为主设备号   minor为次设备号

成功执行返回dev_t类型的设备编号,dev_t类型是unsigned int 类型,32位,用于在驱动程序中定义设备编号,高12位为主设备号,低20位为次设备号

可以通过MAJOR(dev)和MINOR(dev)来获得主设备号和次设备号。

原文链接:https://blog.csdn.net/u011328417/article/details/51968578

1.3 cdev.h

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类型是是字符设备描述的结构, 其中的设备号dev,必须用“dev_t”类型来描述,高12位为主设备号,低20位为次设备号。

 

2. 静态申请字符类设备号

2.1 代码

equest_cdev_num.c

说明:register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME)中,DEVICE_MINOR_NUM代表次设备的个数。

#include 
/*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/#include
/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*//*定义module_param module_param_array的头文件*/#include
/*定义module_param module_param_array中perm的头文件*/#include
/*三个字符设备函数*/#include
/*MKDEV转换设备号数据类型的宏定义*/#include
/*定义字符设备的结构体*/#include
#define DEVICE_NAME "scdev"#define DEVICE_MINOR_NUM 2#define DEV_MAJOR 0#define DEV_MINOR 0MODULE_LICENSE("Dual BSD/GPL");/*声明是开源的,没有内核版本限制*/MODULE_AUTHOR("iTOPEET_dz");/*声明作者*/int numdev_major = DEV_MAJOR;int numdev_minor = DEV_MINOR;/*输入主设备号*/module_param(numdev_major,int,S_IRUSR);/*输入次设备号*/module_param(numdev_minor,int,S_IRUSR);static int scdev_init(void){ int ret = 0; dev_t num_dev; printk(KERN_EMERG "numdev_major is %d!\n",numdev_major); printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor); if(numdev_major){ num_dev = MKDEV(numdev_major,numdev_minor); ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME); } else{ printk(KERN_EMERG "numdev_major %d is failed!\n",numdev_major); } if(ret<0){ printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); } printk(KERN_EMERG "scdev_init!\n"); /*打印信息,KERN_EMERG表示紧急信息*/ return 0;}static void scdev_exit(void){ printk(KERN_EMERG "scdev_exit!\n"); unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);}module_init(scdev_init);/*初始化函数*/module_exit(scdev_exit);/*卸载函数*/

Makefile

#!/bin/bash#通知编译器我们要编译模块的哪些源码#这里是编译itop4412_hello.c这个文件编译成中间文件mini_linux_module.oobj-m += request_cdev_num.o #源码目录变量,这里用户需要根据实际情况选择路径#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的KDIR := /home/topeet/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

2.2 调试记录:

insmod request_cdev_num.ko numdev_major=9 numdev_minor=0

rmmod request_cdev_num.ko numdev_major=9 numdev_minor=0

3. 动态申请字符类设备号

3.1 驱动代码

request_acdev_num.c

#include 
/*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/#include
/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*//*定义module_param module_param_array的头文件*/#include
/*定义module_param module_param_array中perm的头文件*/#include
/*三个字符设备函数*/#include
/*MKDEV转换设备号数据类型的宏定义*/#include
/*定义字符设备的结构体*/#include
#define DEVICE_NAME "acdev"#define DEVICE_MINOR_NUM 2#define DEV_MAJOR 0#define DEV_MINOR 0MODULE_LICENSE("Dual BSD/GPL");/*声明是开源的,没有内核版本限制*/MODULE_AUTHOR("iTOPEET_dz");/*声明作者*/int numdev_major = DEV_MAJOR;int numdev_minor = DEV_MINOR;/*输入主设备号*/module_param(numdev_major,int,S_IRUSR);/*输入次设备号*/module_param(numdev_minor,int,S_IRUSR);static int acdev_init(void){ int ret = 0; dev_t num_dev; printk(KERN_EMERG "numdev_major is %d!\n",numdev_major); printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor); if(numdev_major){ num_dev = MKDEV(numdev_major,numdev_minor); ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME); } else{ /*动态注册设备号*/ ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME); /*获得主设备号*/ numdev_major = MAJOR(num_dev); printk(KERN_EMERG "adev_region req %d !\n",numdev_major); } if(ret<0){ printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); } printk(KERN_EMERG "acdev_init!\n"); /*打印信息,KERN_EMERG表示紧急信息*/ return 0;}static void acdev_exit(void){ printk(KERN_EMERG "acdev_exit!\n"); unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);}module_init(acdev_init);/*初始化函数*/module_exit(acdev_exit);/*卸载函数*/

Makefile

#!/bin/bash#通知编译器我们要编译模块的哪些源码#这里是编译itop4412_hello.c这个文件编译成中间文件mini_linux_module.oobj-m += request_acdev_num.o #源码目录变量,这里用户需要根据实际情况选择路径#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的KDIR := /home/topeet/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

3.2 代码调试

[root@iTOP-4412]# insmod request_acdev_num.ko 

[root@iTOP-4412]# rmmod request_acdev_num

你可能感兴趣的文章