博客
关于我
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/

你可能感兴趣的文章
PostgreSQL学习总结(6)—— PostgreSQL 模式(SCHEMA)详解
查看>>
PostgreSQL学习总结(7)—— PostgreSQL 语句 INSERT INTO、SELECT、UPDATE、DELETE 等学习
查看>>
PostgreSQL学习总结(8)—— PostgreSQL 基于数据库和基于模式(schema)的多租户分析
查看>>
PostgreSQL学习总结(9)—— PostgreSQL 运算符与表达式
查看>>
PostGreSql学习笔记001---PostgreSQL10.4安装(Windows)_支持PostGreGis_PostJDBC
查看>>
PostGreSql学习笔记002---Navicat Premium中管理PostGreSql 错误:字段rolcatupdate 不存在
查看>>
PostgreSQL学习笔记:PostgreSQL vs MySQL
查看>>
PostgreSQL实现shape数据转geojson数据(地图工具篇.18)
查看>>
PostgreSQL导入shape数据(地图工具篇.10)
查看>>
PostGreSql工作笔记003---在Navicat中创建数据库时报错rolcatupdate不存在_具体原因看其他博文_这里使用pgAdmin4创建管理postgre
查看>>
PostGreSql工作笔记004---PostGreSql修改密码_windows和linux下修改
查看>>
Postgresql常用命令行操作_以及Navicat操作PostGis时的问题_自动截取长度_WKB structure does not match exp---PostgreSQL工作笔记005
查看>>
PostgreSQL忘记密码
查看>>
PostgreSQL数据库pg_dump命令行不输入密码的方法
查看>>
PostgreSQL新手入门
查看>>
postgresql树状结构查询示例
查看>>
PostgreSQL流复制参数max_wal_senders详解
查看>>
postgresql流复制配置
查看>>
PostgreSQL清空表并保留表结构、清空数据库还原数据库为新建时的状态的方法
查看>>
PostgreSQL的 initdb 源代码分析之九
查看>>