驱动开发--初识(字符设备scull)

  由于工作需要,学习驱动开发。学习的主要参考资料是LDD3。操作系统为Ubuntu164.

 

  scull( Simple Character Utility for Loading Localities)是一个字符驱动,scull只是操作从内核分配的内存,不依赖硬件,操作一块内存区域就好像这块内存是一个设备(也是Linux操作系统的精妙所在)。所以以它为开始学习的起点便于我们学习。

  如果在  /dev  目录下输入  ls -l  会显示如下:

total 0
crw-------  1 root root     10, 235 11月  7 08:44 autofs
drwxr-xr-x  2 root root         360 11月  7  2018 block
drwxr-xr-x  2 root root          60 11月  7  2018 bsg
crw-------  1 root root     10, 234 11月  7 08:44 btrfs-control
drwxr-xr-x  3 root root          60 11月  7  2018 bus
drwxr-xr-x  2 root root        3780 11月  7 08:44 char
crw-------  1 root root      5,   1 11月  7 08:44 console
lrwxrwxrwx  1 root root          11 11月  7  2018 core -> /proc/kcore
drwxr-xr-x  2 root root          60 11月  7  2018 cpu
crw-------  1 root root     10,  59 11月  7 08:44 cpu_dma_latency
crw-------  1 root root     10, 203 11月  7 08:44 cuse
drwxr-xr-x  5 root root         100 11月  7  2018 disk
drwxr-xr-x  2 root root         100 11月  7  2018 dri
crw-------  1 root root     10,  61 11月  7 08:44 ecryptfs
crw-rw----  1 root video    29,   0 11月  7 08:44 fb0
lrwxrwxrwx  1 root root          13 11月  7  2018 fd -> /proc/self/fd
brw-rw----  1 root disk      2,   0 11月  7 08:44 fd0
crw-rw-rw-  1 root root      1,   7 11月  7 08:44 full
crw-rw-rw-  1 root root     10, 229 11月  7 08:44 fuse

其中最后修改日期前面的数表示主设备号和次设备号,如最后一行的10,229;

解释一下  /dev  目录:这里并不是放的外部设备的驱动程序。这一点和我们常用的windows操作系统不一样。它实际上是一个访问这些外部设备的端口。我们可以非常方便地去访问这些外部设备,和访问一个文件,一个目录没有任何区别。

  MAJOR(dev_t dev);      //获得主设备号

  MINOR(dev_t dev);      //获得次设备号

如果有设备号需要将其转换为一个dev_t,使用:

  MKDEV(int major,int minor);

  在内核中, dev_t 类型(在 <linux/types.h>中定义)用来持有设备编号 -- 主次部分都包括. 对于 2.6.0 内核, dev_t 是 32 位的量, 12 位用作主编号, 20 位用作次编号.其定义如下:

    #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))

 

  int register_chrdev_region(dev_t first, unsigned int count, char *name);//自己分配设备号
  这里, first 是你要分配的起始设备编号. first 的次编号部分常常是 0, 但是没有要求是那个效果. count
是你请求的连续设备编号的总数. 注意, 如果 count 太大, 你要求的范围可能溢出到下一个次编号;
但是只要你要求的编号范围可用, 一切都仍然会正确工作.

 

  int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);//动                                       态分配设备号
  使用这个函数, dev 是一个只输出的参数, 它在函数成功完成时持有你的分配范围的第一个数.
fisetminor 应当是请求的第一个  

 

  void unregister_chrdev_region(dev_t first, unsigned int count);//释放设备号
  调用 unregister_chrdev_region 的地方常常是你的模块的 cleanup 函数.

 

posted on 2018-12-11 17:41  未知生命  阅读(265)  评论(0编辑  收藏  举报

导航