设备编号的组成
在任意一个字符设备文件中,都可以查到主设备编号和次设备编号
-
字符设备编号的数据类型:dev_t的数据类型,定义在头文件中。其中12位用于主编号,20位用于次编号。
-
主编号:用于表示设备的种类,对于同一主编号的多个设备是由同一个驱动管理。
-
次编号:表示在同一种类中的多个设备的编号。
设备号组合和拆分的宏
#include <linux/kdev_t.h>
/*已知设备编号得到主编号和次编号*/
MAJOR(dev_t dev);
MINOR(dev_t dev);
/*已知主次设备号得到设备号*/
MKDEV(int major, int minor); /* major表示主设备号,minor表示次设备号 */
设备号的申请和释放
#include <linux/fs.h>
/**
* [register_chrdev_region 手动申请设备号]
* @param from [设备号]
* @param count [申请设备号的个数]
* @param name [设备名称]
* @return [成功0 失败返回错误码]
*/
int register_chrdev_region(dev_t from, unsigned count, const char *name);
/**
* [alloc_chrdev_region 动态申请设备号]
* @param dev [接收申请成功的设备号,所有使用指针]
* @param baseminor [起始次设备号]
* @param count [申请设备号的总数]
* @param name [设备名称]
* @return [成功0 失败返回错误码]
*/
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name);
/**
* [unregister_chrdev_region 设备号的释放]
* @param from [释放的设备号]
* @param count [释放的个数]
*/
void unregister_chrdev_region(dev_t from, unsigned count);
实例
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
MODULE_LICENSE("GPL");
static dev_t dev = MKDEV(255, 0);/* 定义设备号变量(动态申请不需要初始化) */
static unsigned int count = 1;
/* 定义模块加载函数 */
static int __init my_module_init(void)
{
int ret;
/* 申请设备编号 */
#if 0
/* 手动申请设备号 */
ret = register_chrdev_region(dev, count, "mychar");
if (ret != 0)
{
printk(KERN_ERR "register_chrdev_region: ret = %d\n", ret);
return ret;
}
#else
/* 动态申请设备号 */
ret = alloc_chrdev_region(&dev, 0, count, "mychar");
if (ret != 0)
{
printk(KERN_ERR "register_chrdev_region: ret = %d\n", ret);
return EINVAL;
}
#endif
printk(KERN_INFO "register_chrdev_region major:%d,minor:%d\n", MAJOR(dev), MINOR(dev));
return 0;
}
/* 定义模块卸载函数 */
static void __exit my_module_exit(void)
{
/* 释放设备号 */
unregister_chrdev_region(dev, count);
}
/* 声明模块的加载入口 */
module_init(my_module_init);
/* 声明模块的卸载入口 */
module_exit(my_module_exit);
返回的错误码
#define EPERM 1/* 不允许操作 */
#define ENOENT 2/* 没有这样的文件或目录 */
#define ESRCH 3/* 没有这样的过程 */
#define EINTR 4/* 中断的系统调用 */
#define EIO 5/* I/O错误 */
#define ENXIO 6/* 没有此类设备或地址 */
#define E2BIG 7/* 参数列表太长 */
#define ENOEXEC 8/* 执行文件格式错误 */
#define EBADF 9/* 错误的文件号 */
#define ECHILD 10/* 没有子进程 */
#define EAGAIN 11/* 再试一次 */
#define ENOMEM 12/* 内存不足 */
#define EACCES 13/* 权限不足 */
#define EFAULT 14/* 错误的地址 */
#define ENOTBLK 15/* 需要块设备 */
#define EBUSY 16/* 设备或资源忙 */
#define EEXIST 17/* 文件存在 */
#define EXDEV 18/* 跨设备链接 */
#define ENODEV 19/* 无此设备 */
#define ENOTDIR 20/* 不是一个目录 */
#define EISDIR 21/* 是一个目录 */
#define EINVAL 22/* 无效参数 */
#define ENFILE 23/* 文件表溢出 */
#define EMFILE 24/* 打开文件过多 */
#define ENOTTY 25/* 不是打字机 */
#define ETXTBSY 26/* 文本文件忙 */
#define EFBIG 27/* 文件太大 */
#define ENOSPC 28/* 磁盘空间不足 */
#define ESPIPE 29/* 非法搜索 */
#define EROFS 30/* 只读文件系统 */
#define EMLINK 31/* 链接太多 */
#define EPIPE 32/* 管道破裂 */
#define EDOM 33/* 参数不在数学函数能接受的域中 */
#define ERANGE 34/* 数学结果不可表示 */
网友评论