Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1247745
  • 博文数量: 261
  • 博客积分: 4196
  • 博客等级: 上校
  • 技术积分: 3410
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-17 17:05
文章分类

全部博文(261)

文章存档

2018年(1)

2017年(22)

2016年(2)

2015年(8)

2014年(27)

2013年(40)

2012年(161)

分类: LINUX

2012-09-20 16:50:35


字符设备

 

字符设备是个能够象字节流(比如文件)一样访问的设备,由字符设备驱动程序来实现这种特性。通过/dev下的字符设备文件来访问。字符设备驱动程序通常至少需要实现 opencloseread write 系统调用。

大多数字符设备是个只能顺序访问的数据通道,不能前后移动访问指针,这点和文件不同。比如串口驱动,只能顺序的读写设备。然而,也存在和数据区或者文件特性类似的字符设备,访问它们时可前后移动访问指针。

 

主设备号和次设备号

主设备号是内核识别一个设备的标识。是一个整数,范围从0(4096-1),但是一般使用1255

次设备号是驱动程序自己用来区别多个设备。是一个整数,范围从0(1048576-1),但是一般使用0255

预定义的设备号:详见Documentation/devices.txt

/dev目录下查看主次设备

 

设备号

  系统用一个dev_t 结构定义变量表示设备号,实际它是主设备号和次设备号的综合。

  怎样通过设备号获得主或者次设备号?

MAJOR(dev_t dev);

      MINOR(dev_t dev);

   怎样通过主次设备号获得设备号?

      MKDEV(int major, int minor);   

 

申请设备号

register_chrdev_region

     主设备号已经确认的情况下使用。

     参数分别是设备号,次设备号数量,设备名称

alloc_chrdev_region

     自动分配主设备号

      参数分别是获取的设备号(输出参数),第一个次设备号,次设备号数量,设备名称

 

字符设备注册

cdev_init

    字符设备初始化。

    参数分别是字符设备结构指针,文件操作结构指针。

cdev_add

    字符设备添加。

    参数分别是字符设备结构指针,设备号,次设备号数量。

 

释放函数接口

cdev_del

    参数是字符设备结构指针。

 

unregister_chrdev_region

    参数分别是设备号,次设备号数量。

 

文件操作

字符驱动和内核的接口:file_operations结构体。结构体多是一些函数指针,我们要实现其中的主要函数。在(include/linux/fs.h)定义。

字符驱动只要实现一个file_operations结构体,并注册到内核中,内核就有了操作此设备的能力。

            file_operations的主要域:

              struct module *owner:指向模块自身。

open:打开设备。

              release:关闭设备。

              read:从设备上读数据。

              write::向设备上写数据。

              ioctl:操作设备函数。

 

打开文件操作

open(struct inode *inode, struct file *filp)

            模块使用计数加1

            识别次设备号,如有必要更新f_op 指针。分配并填写置于filp->private_data 里的数据结构。

            硬件操作:

              检查设备相关错误(诸如设备未就绪或类似的硬件问题)。

              如果设备是首次打开,则对其初始化。

              如果有中断操作,申请中断处理程序。

 

关闭文件操作

release(struct inode *inode, struct file *filp)

            模块使用计数减1

            释放放由open 分配的,保存在filp->private_data中的所有内容

            硬件操作

              如果申请了中断,则释放中断处理程序。

              在最后一次关闭操作时关闭设备

 

读写文件操作

            ssize_t read(struct file *filp, char *buff,  size_t count, loff_t *offp);

            ssize_t write(struct file *filp, const char *buff,  size_t count, loff_t *offp);

参数说明:

                     参数filp 是文件指针,

                     参数buff 是指向用户空间的缓冲区,这个缓冲区或者保存将写入的数据,或者是一个存放新读入数据的空缓冲区。

                     参数count 是请求传输的数据长度。

                     最后的offp 是一个指向“long offset type(长偏移量类型)对象的指针,这个对象指明用户在文件中存取操作的位置。

 

Io控制文件操作

            ioctl函数,为设备驱动程序执行命令提供了一个特有的入口点,用来设置或者读取设备的属性信息。

              int (*ioctl) (struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg);

在用户空间对应的ioctl 系统调用为:

            int ioctl(int d, int cmd, ...);

在用户空间对字符设备调用ioctl系统调用,会最终调用字符设备的ioctl函数。

阅读(841) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~