博客
关于我
17-18_静态和动态申请字符类设备号
阅读量:320 次
发布时间:2019-03-04

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

字符设备驱动开发

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:要分配的设备编号范围的初始值,这组连续设备号的起始设备号。
  • count:连续编号范围,是这组设备号的大小(也是次设备号的个数)。
  • name:编号相关联的设备名称(/proc/devices),本组设备的驱动名称。

(2)alloc_chrdev_region

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
  • 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))
  • MKDEV:将主设备号和次设备号组合成一个 dev_t 类型的设备编号。
  • dev_t 类型是 unsigned int,高12位为主设备号,低20位为次设备号。

1.3 cdev.h

头文件位置 include/linux/cdev.h,定义了 cdev 结构体:

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:设备号,高12位为主设备号,低20位为次设备号。

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

2.1 代码示例

#include 
#include
#include
#include
#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"); 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);

2.2 Makefile

#!/bin/bashobj-m += request_cdev_num.oKDIR := /home/topeet/iTop4412_Kernel_3.0PWD := $(shell pwd)all:    make -C $(KDIR) M=$(PWD) modulesclean:    rm -rf *.mod.c *.o *.order *.ko *.mod.o *.symvers

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

3.1 驱动代码

#include 
#include
#include
#include
#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"); 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);

3.2 代码调试

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

转载地址:http://idwh.baihongyu.com/

你可能感兴趣的文章
python中 将你的名字转化成为二进制并输出
查看>>
Python中*args 和**kwargs的用法
查看>>
Python中*args 和**kwargs的用法
查看>>
Python中*args和**kwargs的使用
查看>>
python中0、1、True、False、if条件
查看>>
python中argparse模块关于 parse_args() 函数详解(全)
查看>>
python中base64编码与解码
查看>>
python中break怎么用_详解Python中break语句的用法
查看>>
python中del函数的垃圾回收
查看>>
Python中DrissionPage的详细解析与实战
查看>>
python中enumerate、变量类型转换
查看>>
python中execute是啥_python – 为什么“c.execute(…)”打破循环?
查看>>
python中exit和break区别_Python中exit()和sys.exit()之间的区别
查看>>
python中h5的用法
查看>>
python中http协议编程_HTTP编程
查看>>
python中import os_Python:相对导入与绝对导入(import)、os.path、__file__
查看>>
python中is和==操作符
查看>>
Python中range对象的使用以及打印九九乘法表
查看>>
Python中set.discard和set.remove方法之间的运行时差异?
查看>>
python中tkinter中value_输入字段中的python Tkinter get()值
查看>>