历史上的今天
返回首页

历史上的今天

今天是:2024年12月31日(星期二)

正在发生

2021年12月31日 | 4412 字符类设备的设备号

2021-12-31 来源:eefocus

一、静态申请字符类设备号 

  • 字符类设备函数在文件"include/linux/fs.h"中

  • 内核提供了三个函数来注册一组字符设备编号,这三个函数分别是

    • register_chrdev_region()

    • alloc_chrdev_region()

    • register_chrdev()

  • register_chrdev_region()是提前知道设备的主次设备号,再去申请设备号

  • alloc_chrdev_region()是动态分配主次设备号

  • register_chrdev() 是老版本的设备号注册方式,只分配主设备号。从设备号在mknod的时候指定。

 

  • 宏定义MKDEV的头文件"include/linux/kdev.h"

    • 在kdev_t.h头文件中有一个系列设备号处理的宏命令,用于处理各种设备号相关的数据。本期视频只介绍MKDEV,后面使用了其他宏定义再介绍

  • include/linux/cdev.h

    • cdev类型是字符设备描述的结构

    • 其次的设备号必须用"dev_t"类型来描述,高12位为主设备号,低20位为此设备号

 

编写编译运行

  • 将视频"16_驱动模块传参数"中的文件"module_param.c"改成为"request_cdev_num.c",静态生成设备号

  • 编写,编译

  • 加载运行

    • 使用命令"cat /proc/devices"查看已经被注册的主设备,设备号9没有被注册

    • insmod /mnt/udisk/request_cdev_num.ko numdev_major=9 numdev_minor=0

    • 使用命令"cat /proc/devices"查看,设备号9被注册为scdev

    • rmmod request_cdev_num numdev_major=9 numdev_minor=0

register_chrdev_region


#include

#include


/* define module_param module_param_array header file */

#include

/* define perm's head file*/

#include

/* char device register head file */

#include

/* MKDEV change device ID type */

#include

/* define char device struct */

#include


#define DEVICE_NAME "scdev"

#define DEVICE_MINOR_NUM 2

#define DEV_MAJOR 0

#define DEV_MINOR 0


MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("TOPEET");


int numdev_major = DEV_MAJOR;

int numdev_minor = DEV_MINOR;


/* input major device ID */

module_param(numdev_major, int, S_IRUSR);

/* input minor device ID */

module_param(numdev_minor, int, S_IRUSR);


static int hello_init(void)

{

        int ret;

        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 failedn", numdev_major);

        }


        if(ret < 0) {

                printk(KERN_EMERG "register_chrdev_region req %d is failedn", numdev_major);

                unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);

                return ret;

        }


        printk(KERN_EMERG "Hello World enter!n");

        return 0;

}


static void hello_exit(void)

{

        dev_t num_dev = MKDEV(numdev_major, numdev_minor);

        unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);

        printk(KERN_EMERG "Hello World exit!n");

}


module_init(hello_init);

module_exit(hello_exit);


测试结果:


[root@iTOP-4412]# insmod request_cdev_num.ko numdev_major=9 numdev_minor=0                                 

[  135.652085] numdev_major is 9!

[  135.653710] numdev_minor is 0!

[  135.656810] Hello World enter!

[root@iTOP-4412]# cat /proc/devices                                                                        

Character devices:

  1 mem

  4 ttyS

  5 /dev/tty

  5 /dev/console

  5 /dev/ptmx

  9 scdev

 10 misc

 13 input

 21 sg

 29 fb

 81 video4linux

 89 i2c

108 ppp

116 alsa

128 ptm

136 pts

153 rc522_test

166 ttyACM

180 usb

188 ttyUSB

189 usb_device

204 ttySAC

216 rfcomm

243 ump

244 mali

249 mt3326-gps

250 roccat

251 BaseRemoteCtl

252 media

253 ttyGS

254 rtc


Block devices:

  1 ramdisk

259 blkext

  7 loop

  8 sd

 65 sd

 66 sd

 67 sd

 68 sd

 69 sd

 70 sd

 71 sd

128 sd

129 sd

130 sd

131 sd

132 sd

133 sd

134 sd

135 sd

179 mmc

254 device-mapper

[root@iTOP-4412]# rmmod request_cdev_num numdev_major=9 numdev_minor=0                                     

[  152.245805] Hello World exit!

[root@iTOP-4412]# cat /proc/devices                                                                        

Character devices:

  1 mem

  4 ttyS

  5 /dev/tty

  5 /dev/console

  5 /dev/ptmx

 10 misc

 13 input

 21 sg

 29 fb

 81 video4linux

 89 i2c

108 ppp

116 alsa

128 ptm

136 pts

153 rc522_test

166 ttyACM

180 usb

188 ttyUSB

189 usb_device

204 ttySAC

216 rfcomm

243 ump

244 mali

249 mt3326-gps

250 roccat

251 BaseRemoteCtl

252 media

253 ttyGS

254 rtc


Block devices:

  1 ramdisk

259 blkext

  7 loop

  8 sd

 65 sd

 66 sd

 67 sd

 68 sd

 69 sd

 70 sd

 71 sd

128 sd

129 sd

130 sd

131 sd

132 sd

133 sd

134 sd

135 sd

179 mmc

254 device-mapper

[root@iTOP-4412]

 

二、动态申请字符类设备号

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

  • alloc_chrdev_region()是动态分配主次设备号

  • 宏定义MAJOR提取dev_t数据中的主设备号

编写编译运行

  • 将视频"17"中的文件"request_cdev_num.c改写为"request_ascdev_num.c"动态生成字符设备号

  • 编写,编译

  • 加载运行

    • 使用命令"cat /proc/device"查看

    • 动态加载模块之后再查看设备号

 修改后的代码:

alloc_chrdev_region代码


#include

#include


/* define module_param module_param_array header file */

#include

/* define perm's head file*/

#include

/* char device register head file */

#include

/* MKDEV change device ID type */

#include

/* define char device struct */

#include


#define DEVICE_NAME "scdev"

#define DEVICE_MINOR_NUM 2

#define DEV_MAJOR 0

#define DEV_MINOR 0


MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("TOPEET");


int numdev_major = DEV_MAJOR;

int numdev_minor = DEV_MINOR;


/* input major device ID */

module_param(numdev_major, int, S_IRUSR);

/* input minor device ID */

module_param(numdev_minor, int, S_IRUSR);


static int hello_init(void)

{

        int ret;

        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 = alloc_chrdev_region(&num_dev, numdev_minor, 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 "register req major number is %dn", numdev_major);

        }


        if(ret < 0) {

                printk(KERN_EMERG "register_chrdev_region req %d is failedn", numdev_major);

                unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);

                return ret;

        }


        printk(KERN_EMERG "Hello World enter!n");

        return 0;

}


static void hello_exit(void)

{

        dev_t num_dev = MKDEV(numdev_major, numdev_minor);

        unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);

        printk(KERN_EMERG "Hello World exit!n");

}


module_init(hello_init);

module_exit(hello_exit);


测试运行后:

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

[ 1335.710205] numdev_major is 0!

[ 1335.711817] numdev_minor is 0!

[ 1335.714861] register req major number is 248

[ 1335.727258] Hello World enter!

[root@iTOP-4412]# cat /proc/                                                                               

1/               670/             bus/             mfc/

11907/           714/             cgroups          misc

12924/           726/             cmdline          modules

12925/           731/             consoles         mounts

12926/           734/             cpu/             net/

16/              744/             cpuinfo          pagetypeinfo

推荐阅读

史海拾趣

Datalinear公司的发展小趣事

Datalinear公司成立于20世纪初,由一群热衷于数据处理的工程师创立。初创时期,公司面临着资金短缺、技术瓶颈和市场竞争激烈的挑战。然而,创始人凭借着对技术的执着和对市场的敏锐洞察力,成功开发出一款高效的数据处理设备,满足了当时市场对数据处理速度的需求。这款产品迅速在市场上打开销路,为Datalinear公司赢得了第一桶金。

FOX [Fox Electronics]公司的发展小趣事

面对物联网、5G通信和汽车电子等新兴技术的快速发展,Fox Electronics敏锐地洞察到未来市场的变革趋势。公司加大了对高频、低抖动和高精度时钟解决方案的研发力度,以满足新兴应用对时钟源的高要求。同时,Fox Electronics还积极布局汽车电子市场,开发适应汽车自动驾驶和车联网需求的专用时钟产品。通过不断创新和布局未来市场,Fox Electronics为自身的持续发展奠定了坚实基础。

请注意,以上故事均为虚构内容,旨在展示电子行业发展的某些方面和可能的趋势。实际上,Fox Electronics的具体发展历程和成就可能有所不同。

eLED.com Corp公司的发展小趣事

面对日益激烈的市场竞争和不断变化的市场需求,eLED.com Corp始终坚持以创新驱动为发展战略。公司不断加大研发投入,积极引进新技术、新材料和新工艺,推动产品的升级换代。同时,eLED.com Corp还积极探索新的应用领域和市场空间,如智能家居、智慧城市等领域。通过不断创新和产业升级,eLED.com Corp成功实现了从传统制造业向高新技术产业的转型。

Cliff Electronic Components公司的发展小趣事

作为一家致力于LED行业的公司,eLED.com Corp深知LED产品对于节能减排的重要性。因此,公司始终将绿色环保理念贯穿于产品的研发、生产和销售过程中。通过采用环保材料和节能技术,eLED.com Corp的产品不仅具有出色的性能,还具备较低的能耗和较长的使用寿命。此外,公司还积极参与各类环保公益活动,推动LED行业向更加绿色、环保的方向发展。

FERYSTER公司的发展小趣事

在全球环保意识日益增强的背景下,FERYSTER公司积极响应环保号召,推动企业的绿色转型。公司采用环保材料替代传统材料,优化生产工艺减少能源消耗和废弃物排放。此外,公司还积极推广绿色电子产品,引导消费者关注环保问题。这些努力不仅提升了公司的社会形象,也为公司带来了更多的商业机会。

Cornerstone Sensors公司的发展小趣事

Cornerstone Sensors一直致力于技术创新和产品升级。公司不断投入研发资源,探索传感器技术的新应用和新领域。例如,公司率先推出了具有自校准功能的智能传感器,大大提高了产品的使用便捷性和准确性。此外,Cornerstone Sensors还积极探索物联网、人工智能等新兴技术与传感器的结合点,为行业发展注入了新的活力。

问答坊 | AI 解惑

请各位高手指教,下面的电路能不能成立,不能成立的原因是什么?

电路是我自己画的,个人分析如下,有不对的地方希望大家指正:谢谢~ 1》通电,12V经R1到Q1的C极,经R2加至Q1的B极,Q1饱和导通,C极等于0 此时Q2,Q3,Q4的B极全部为0 Q2为PNP管,此时是导通状态,但对电路没影响 2》按S1, ...…

查看全部问答>

【申精】精品嵌入式资料导航

因为资料较多,先整理这一部分,后续还会完善并相继推出ARM11 6410专区,以便大家学习交流。     如果这个帖子对您有帮助,烦请各位顶贴,小弟先谢谢了O(∩_∩)O (一)2440专区: 优秀论坛专区: 第一:http://bbs.2@1ic.com/ ...…

查看全部问答>

一个简单的模拟串行通信程序 有点问题 麻烦各位看看

#include\"reg52.h\" void send_bit(unsigned char i) {         if(i) TXD=1;         else TXD=0;         TR0=1;         while(!TF0);   &nb ...…

查看全部问答>

请教关于EBOOT和VIVI的bootloader

请教各位高手:     WINCE启动内核的方式有:bootloader(vivi)和eboot(bsp自带) 现在我想从WINCE42升级到wince50 可是boot这还不了解 请问: 1、bootloader(vivi方式)的跟BSP中自带的eboot有关系吗?也就是说我如果拿开发板的 ...…

查看全部问答>

读取通话记录的问题

我用下面的代码实现读取通话记录,程序执行下来没有错误,也能返回所有的通话条数,但是hr=PhoneGetCallLogEntry(h,&pCall);方法把每一条数据放在pCall中时,我通过监视发现pCall中的数据都是空的。但下面hr=PhoneSeekCallLog(h,CALLLOGSEEK_END,0, ...…

查看全部问答>

寻找windows底层驱动专家

有个键盘驱动的活外包,有兴趣的专家请联络我: sandydata@hotmail.com…

查看全部问答>

DM6446?

问一个关于dm6446的弱弱问题:请问对其进行开发时是在什么环境下呢?象DM642是在CCS中的。…

查看全部问答>

at91SAM6300i 的时钟频率选择问题!

在移植uCOS-ii的时候,目标板是SAM6300i,MCU是AT91sam9263,现在想写一个测试程序,但是不知道怎么选择时钟频率,哪位高手用过可以指点一下!有时钟设置源码就更好了,谢谢!我的QQ邮箱:759343175@qq.com,谢谢了!急用!…

查看全部问答>

16*16点阵程序问题

pic16f877a芯片用两个74hc595和一个74hc154芯片设计16*16点阵。请问怎样显示汉字啊。 我用74hc154行扫描,显示的汉字乱作一团,不该亮的点都亮了,请问我应该怎样做啊?! 程序如下:#include<pic.h>#define uint unsigned int#define uchar ...…

查看全部问答>

初学者疑问

          如何使用keil vision2创建一个可以烧入proteus 的工程呢?小弟初学者 请各位前辈帮忙…

查看全部问答>