字符设备驱动(1)

主次设备号

字符设备通过字符设备文件来存取。字符设备文件由使用ls -l 的输出的第一列的“C”标识。如果使用ls -l命令,会看到在设备文件项中有两个数(由一个逗号分隔),这些数字就是设备文件的主次设备编号。(举例查看 /dev)

设备号作用

主设备号用来标识与设备文件相连的驱动程序。次设备号被驱动用来决定操作的是哪个设备。
** 主设备号用来体现设备类型
** 次设备号用来体现某种设备类型中的第几个

Q: 内核中如何描述设备号

A:struct dev_t ,实质为unsigned int 32位整数,其中高12为主设备号,低20位为次设备号。

Q: 如何从kdev_t结构体分解主设备号

A: MAJOR(dev_t dev)

Q: 如何从kdev_t结构体 中分解出次设备号

A: MINOR(dev_t dev)

Q: 如何构造设备号

A: dev_t MKDEV(unsigned int major, unsigned int minor)

分配设备号

Q:Linux内核如何给设备分配设备号

A : 可以采用静态分配、动态分配两种方法

静态分配

1、根据documentation/devices.txt, 找到一个没有使用的设备号,并手动指定。
2、使用register_chrdev_region函数注册

dev = MKDEV(devmajor,devminor); //获得设备号
result = register_chrdev_region(dev,1,"demo");//分配设备号

3、缺点:一旦驱动更广泛的被使用,一个随机获取的主设备号将导致冲突。

静态申请

int register_chrdev_region(dev_t from, unsigned count, const char *name)

功能:
申请使用从 from 开始的 count 个设备号(主设备号
不变,次设备号增加)
参数:
from:希望申请使用的设备号
count:希望申请使用设备号数目
name:设备名(体现在/proc/devices)

动态分配

方法:使用alloc_chrdev_region分配设备号
优点:
简单,易于驱动推广
缺点:
无法在安装驱动前创建设备文件,因为还没有分配到主设备号。
解决办法:
一旦驱动程序安装、主设备号分配了, 可从 /proc/devices 中查询到

result = alloc_chrdev_region(&dev, devminor, 1,	“led”);//2  动态分配设备编号	
devmajor = MAJOR(dev);

动态申请

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)

功能:
请求内核动态分配 count 个设备号,且次设备号从baseminor开始。
参数:
dev:分配到的设备号
baseminor:起始次设备号
count:需要分配的设备号数目
name:设备名(体现在/proc/devices)

注销设备号

不论使用何种方法分配设备号,都应该在不再使用它们时释放这些设备号。

void unregister_chrdev_region(dev_t from,unsigned count)

功能:
释放从from开始的count个设备号

设备驱动安装

安装一个字符设备驱动的方法:
设备号手工指定:

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

first :要分配的设备编号范围的初始值(次设备号常设为0);
count:连续编号范围.
name:编号相关联的设备名称. (可查看:cat /proc/devices);

设备号自动获取:

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

firstminor : 通常为0;
*dev:存放返回的设备号;

卸载一个字符设备驱动的方法:

void unregister_chrdev_region(dev_t first, unsigned int count);

驱动注册示例代码

if (scull_major)
{ 
	dev = MKDEV(scull_major, scull_minor); 
	result = register_chrdev_region(dev, scull_nr_devs, "scull"); 
} else
{ 
	result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull"); 
	scull_major = MAJOR(dev);
} 
if (result < 0) 
{ 
	printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
	return result; 
} 

创建设备文件

1、使用mknod命令手动创建
2、使用devfs提供的函数在驱动程序中自动创建

mknod 用法:

# mknod filename type major minor

Filename:设备文件名
Type: 设备文件类型
Major: 主设备号
Minor: 次设备号
例: mknod /dev/serial0 c 100 0

自动创建

设备文件系统有:devfs、udev、mdev等。 不同的设备文件系统的创建节点的方法不同。2.6.12( devfs ),2.6.13以后就很少使用了。

#ifdef CONFIG_DEVFS_FS  
devfs_mk_cdev(dev, S_IFCHR|S_IRUGO|S_IWUSR, "led_su");  
#endif

2.6.32( mdev,是udev的简化,用于嵌入式 ),Udev用于PC机,

struct class *led_class;
/* create your own class under /sysfs   2.6.32*/
led_class = class_create(THIS_MODULE, "led_class");
if(IS_ERR(led_class)) 
{
	printk("Err: failed in creating class.\n");
	return -1; 
}
  
/* register your own device in sysfs, and this will cause udev to create corresponding device node */
device_create( led_class, NULL, MKDEV(devmajor, 0),  NULL, "led_su");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值