Linux设备驱动程序学习----9.主设备号和次设备号

9.主设备号和次设备号

更多内容请参考Linux设备驱动程序学习----目录

  本章的目标是编写一个模块化的字符设备驱动程序。在本书中,取设备驱动程序名称为:scull,即 Simple Character Utility for Loading Localities,区域装载的简单字符工具。scull是一个操作内存区域的字符设备驱动程序,这片内存区域相当于一个设备。

  scull的优点在于它不和硬件相关,而只是操作从内核中分配的一些内存。scull可以随便编译和运行,scull可以被移植到Linux支持的计算机平台上,scull还可以展示内核和字符设备驱动程序之间的接口并让用户运行某些测试例程。但是scull设备在实际上并不会操作外部设备。

scull的设计

  编写设备驱动程序的第一步是定义驱动程序为用户程序提供的机制。由于scull是计算机内存的一部分,所以它可以随意被操作,可以是顺序或随机存取设备,也可以是一个或多个设备等。

主设备号和次设备号

  对字符设备的访问是通过文件系统内的设备名称进行的,即特殊文件、设备文件,或者被称为文件系统树的节点,通常位于/dev目录。

  字符设备驱动程序的设备文件可通过ls -l命令输出的第一列中的字符'c'来识别。块设备也在/dev下,由字符'b'标识。

  执行 ls -l 命令,在设备文件的最后修改日期前有两个数(用逗号分隔),对于普通文件代表文件的长度,而对于设备文件,就是相应设备的主设备号和次设备号。

  通常,主设备号标识设备对应的驱动程序。现代的Linux内核允许多个驱动程序共享主设备号,但大多数设备按照“一个主设备号对应一个驱动程序”的原则。

  次设备号由内核使用,用于确定设备文件所指的设备。

设备编号的内部表达

  在内核中,dev_t类型用来保存设备编号--包括主设备号和次设备号,包含在头文件<linux/types.h>中。在内核Linux2.6.0版本中,dev_t是一个32位的数,其中的12位用来表示主设备号,其余20位用来表示次设备号,设备编号应该使用<linux/kdev_t.h>中定义的宏。获取dev_t的主设备号或次设备号,应使用:

MAJOR(dev_t dev);
MINOR(dev_t dev);

如果需要将主设备号和次设备号转换成dev_t类型,则使用:

MKDEV(int major, int minor);

分配和释放设备编号

  在建立一个字符设备之前,驱动程序需要获得一个或多个设备编号。

静态申请设备编号

  如果提前确定所需要的设备编号,可以通过register_chrdev_region()函数注册设备编号:

#include <linux/fs.h>

int register_chrdev_region(dev_t first, unsigned int count, char *name);

参数说明:
first: 要分配的设备编号范围的起始值;
count: 所请求的连续设备编号的个数;
name: 是和该编号范围关联的设备名称,将出现在/proc/devices和sysfs中;
返回值:
分配成功时返回0;
错误时返回一个负的错误码,并且不能使用所请求的编号区域;

动态申请设备编号

  如果不知道设备将要使用的设备编号,可以通过alloc_chrdev_region()函数注册设备编号:

#include <linux/fs.h>

int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);

参数说明:
dev: 用于输出参数,函数执行成功时,将保存已分配范围的第一个设备编号;
firstminor: 要使用的被请求的第一个次设备号,通常是0;
count: 所请求的连续设备编号的个数;
name: 和该编号范围关联的设备名称,将出现在/proc/devices和sysfs中;

释放设备编号

  在不使用申请的设备编号时,要释放这些设备编号,通常在模块的清除函数中释放申请的设备编号;设备编号的释放需要使用以下函数实现:

#include <linux/fs.h>

void unregister_chrdev_region(dev_t first, unsigned int count);

  通过以上方法,位驱动程序的使用分配设备编号,但是在用户空间程序访问设备编号,驱动程序需要将设备编号和内部函数连接起来,而这些内部函数用来实现设备的操作。

动态分配主设备号

  部分主设备号已经静态地分配给了常用设备,在内核的Documentation/devices.txt文件中可以查到设备清单,驱动程序申请设备编号可以由以下两个选择:

  1. 简单选定一个尚未被使用的主设备号;此方法适用于只有我们自己使用驱动程序的情况;
  2. 通过动态方式分配主设备号;此方法适用于驱动程序被广泛使用时的情况;此时选定的主设备号可能造成冲突和麻烦;

  对于一个新的驱动程序,建议不要随便选择一个当前未使用的设备号作为主设备号,应该使用动态分配机制获取主设备号。驱动程序应始终使用alloc_chrdev_region()函数,而不是register_chrdev_region()函数。

  动态分配主设备号的缺点:由于分配的主设备号不能保证始终一致,无法预先创建对应的设备节点。一旦分配了设备号,就可以从/proc/devices中读取到。

  为了能够加载使用动态主设备号的设备驱动程序,可以使用脚本代替insmod命令加载程序,该脚本在调用insmod之后,读取到/proc/devices以获取新分配的主设备号,然后创建对应的设备文件。

。。。。。。

  反复创建和删除/dev节点有些不必要,如果只是装载和卸载单个驱动程序,则可在第一次创建设备文件之后仅使用rmmod和insmod两个命令;因为动态设备号并不是随机生成的,如果不受其他动态模块影响,可以获取到相同的动态主设备号;但是这个技巧不适用于同时有多个驱动程序存在的场合。

  分配主设备号的最佳方式是:默认采用动态分配,同时保留在加载甚至是编译时指定主设备号的余地。scull驱动程序的实现方式:使用一个全局变量scull_major保存所选择的设备号,一个全局变量scull_minor保存次设备号。scull_major默认值为SCULL_MAJOR,该宏定义在scull.h中,SCULL_MAJOR默认值为0,即采用动态分配设备号。这样既可以在编译前修改SCULL_MAJOR宏定义,也可以通过insmod命令行指定scull_major的值。

  在scull驱动中获取主设备号的代码,如下所示:

if (scull_major) {
    dev = MKDEV(scull_major, scull_minor);
    result = register_chrdev_region(dev, scull_nr, "scull");
} else {
    result = alloc_chrdev_region(&dev, scull_minor, scull_nr, "scull");
    scull_major = MAJOR(dev);
}

if (result < 0) {
    printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
    return result;
}

更多内容请参考Linux设备驱动程序学习----目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,706评论 4 366
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,002评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,462评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,375评论 0 216
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,763评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,849评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,033评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,768评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,490评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,734评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,204评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,566评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,227评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,137评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,934评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,926评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,774评论 2 274