Linux 内核学习笔记之简单字符设备驱动

设备号

内核利用设备号来标识设备。换句话说,每个内核管理的设备都有唯一的设备号。

#define MINORBITS	20
#define MINORMASK	((1U << MINORBITS) - 1)

#define MAJOR(dev)	((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev)	((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi)	(((ma) << MINORBITS) | (mi))

如果对MINORMASK不太理解,可以用下面的例子打印一下二进制表示

#include <iostream>
#include <bitset>
#define MINORBITS	20
#define MINORMASK	((1U << MINORBITS) - 1)
int main() {
    std::bitset<32> x(MINORMASK);
    std::cout << x << '\n';
}
// output 00000000000011111111111111111111

可以看出:设备号被表示位一个32位无符号整数,前12位记录主设备号,用来区分设备的类型,后20位记录次设备号,用来区分同一个设备类型下的不同设备及设备分区。

 

设备号生成

有两种方法:

系统自动分配设备号: 需要传递进次设备号的起始数字,和总设备数。如果最终创建的设备数大约总设备数,虽然创建设备节点可能成功,但是读取数据会失败
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name);
/**                                                                                                                                                                         
 * alloc_chrdev_region() - register a range of char device numbers                                                                                                          
 * @dev: output parameter for first assigned number                                                                                                                         
 * @baseminor: first of the requested range of minor numbers                                                                                                                
 * @count: the number of minor numbers required                                                                                                                             
 * @name: the name of the associated device or driver                                                                                                                       
 *                                                                                                                                                                          
 * Allocates a range of char device numbers.  The major number will be                                                                                                      
 * chosen dynamically, and returned (along with the first minor number)                                                                                                     
 * in @dev.  Returns zero or a negative error code.                                                                                                                         
 */


用户指定设备号
int register_chrdev_region(dev_t from, unsigned count, const char *name);

/**
 * register_chrdev_region() - register a range of device numbers
 * @from: the first in the desired range of device numbers; must include
 *        the major number.
 * @count: the number of consecutive device numbers required
 * @name: the name of the device or driver.
 *
 * Return value is zero on success, a negative error code on failure.
 */

 

设备节点

设备节点的创建使用命令mknod, 删除设备节点使用rm命令。如下:

# 创建字符mknod
#用法:mknod [选项]... 名称 类型 [主设备号 次设备号]
# 创建主设备号位252,次设备号为0的,名字为demo的字符设备节点
mknod /dev/demo -c 252 0

#删除设备节点
rm /dev/demo

#注意: 内核驱动模块的卸载并不会删除设备节点,但读取设备节点会失败。

流程总结

以demo.ko为例,实现驱动正常工作的流程可能是这样子的:

1. 加载内核驱动,生成设备号

insmod demo.ko

// output Major number = 250, minor number = 0

2. 根据设备号,创建设备节点

mknod /dev/demo -c 250 0

3. 用户空间对设备节点进行读写操作

int fd = open("/dev/demo", O_RDONLY);
// 打开成功后可以进行读写

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值