您的位置:首页 > 其它

02 关于设备号,设备节点等一些简单概念

2016-06-02 11:46 441 查看
1,设备
Linux文件系统/dev/下通常存放了一系列设备名称。对设备的访问,即访问这些文件。
ls -l /dev/ 能看到这些设备的一些基本信息。如下图所示
了解过Linux下文件类型的小伙伴应该对哪些是字符设备、块设备不会感到陌生了。(bcd-lsp分别是块、字符、目录、普通、链接、套接字、管道)
root后面 那两个逗号隔开的数字是设备的主设备号和次设备号。那我们跳到下一个概念吧。



2,设备号
设备号分为主设备号和次设备号;
主设备号标识设备对应的驱动程序,次设备号由内核使用,区分同一个类型的多个设备,如两个串口。个人认为了解这些就够了。我们需要重点关注的是驱动程序里面如何表达这些概念,也就是下一步。
dev_t devno   //定义设备号,数据类型为dev_t,实际是一个32位的数。
devno = MKDEV(int major, int minor);  //major minor 即我们看到的程序员给出的203,0等这些数字。习惯上限于255个主设备号,255个次设备号  devno = major << 20 | minor;
int major = MAJOR(dev_t devno);
int minor = MINOR(dev_t devno);   //与上面的相反,如果你想通过dev_t devno获得主设备号和次设备号的话,可以这么做。
3,分配和释放设备号

直接上代码
#include <linux/fs.h>
int register_chrdev_region(dev_t first, unsigned int count, char *name);
void unregister_chrdev_region(dev_t first, unsigned int count);
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
参数说明:
dev_t first :MKDEV();获取得到的设备号,
unsigned int count :连续设备编号的个数
char *name :文件系统中看到的设备驱动的名称,cat /proc/devices 或 ls /dev/下能看到的
初始化时需要register,退出时需要unregister。
alloc顾名思义,动态分配。经常认为通用PC随机分配,嵌入式产品需提前规划好,故尽量用静态。
register成功返回0,失败返回负的错误码,时刻谨记,可能失败,所以要添加if判断。
驱动程序设计师们经常这样写:



4,设备节点
当你驱动程序按上面的步骤写好后,编译并且insmod。你会发现文件系统中:
cat /proc/devices/下会出现你添加的设备名称,和主设备号。但是/dev/下并没有存在你所注册的dev。这是因为你还没有创建设备节点。这时你需要执行如下命令:
mknod /dev/name c $major minor
你可以确定count 个设备节点,根据你代码中register时指定的count个数。
动态分配主设备号有一个缺点:无法预先创建设备节点。不过,你可以通过/proc/devices/中获得。如果要写成脚本自动分配,可以参考书Page 51,有一个很棒的shell脚本,帮我们完成了。
最后附上几行简单的完整的注册设备号程序:
 1 #include <linux/module.h>
  2 #include <linux/init.h>
  3 #include <linux/kernel.h>
  4 #include <linux/fs.h>        //note: register_chrdev need it
  5
  6 MODULE_LICENSE("Dual BSD/GPL");
  7
  8 static int __init scull_init(void)
  9 {
 10         dev_t devno = MKDEV(250, 66);
 11         int ret;
 12
 13         printk(KERN_ALERT "scull dev init\n");
 14         ret = register_chrdev_region(devno, 3, "scull");
 15         if (0 == ret ) {
 16                 printk(KERN_ALERT " register success\n");
 17         } else {
 18                 printk(KERN_ALERT "register fail ret:%d\n", ret);
 19                 goto register_fail;
 20         }
 21
 22         return 0;
 23 register_fail:
 24         unregister_chrdev_region(devno, 1);
 25 }
 26 static void __exit scull_exit(void)
 27 {
 28         dev_t devno = MKDEV(250, 66);
 29
 30         printk(KERN_ALERT "scull exit\n");
 31         unregister_chrdev_region(devno, 1);    
 32 }
 33
 34 module_init(scull_init);
 35 module_exit(scull_exit);                   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: