驱动笔记(2)--字符设备

来源:互联网 发布:封lol端口 编辑:程序博客网 时间:2024/06/05 17:52

主设备号用来标示与设备文件相连的驱动程序,次编号被驱动程序用来辨别操作哪个设备

主设备号反映设备类型,此设备号区分同类型的设备

dev_t 高12位为主设备号,低20位为次设备号

MAJOR(dev_t dev)从dev_t分解出主设备号

MINOR(dev_t dev)从dev_t分解出此设备号

MKDEV(major,minor) 构造设备号;

 

静态申请:1.根据Documentation/devices.txt驱动没有使用的主设备号 2. 使用register_chrdev_region(dev_t form, unsigned count ,constchar *name)函数注册(容易冲突)

From希望使用的设备号,count希望申请使用设备号的数目,name设备名(体现在/proc/devices)

2. 动态分配   alloc_chardev_region(安装驱动前无法创建设备文件)创建设备文件后,通过/proc/devices察看

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

dev分配的设配号,baseminor起始的此设备号,count要分配的设备数目,name设备名

主要设备号:unregister_chrdev_region(dev_tdev, unsigned baseminor)

Mknod filename type major minor  type是字符或块 mknod serial0 c100   0

Linux字符设备驱动3个重要数据结构

Struct file每打开一次都有一个关联的struct file 重要结构loff_t f_pos文件读写位置 struct file_operations *f_op

Struct inode 记录文件的物理上的信息(设备号等),一个文件可以有多个file,但只有一个inode

Struct file_operation *f_op函数指针的集合

struct file_operations mem_fops = {

       .owner= THIS_MODULE,

       .llseek= mem_seek,

       .read= mem_read

       …….

}

读内核代码应用程序怎样访问驱动程序(read_write,c)

系统条用read找到vfs_read根据file结构中找到file_operations中的read

 

 

字符设备使用 structcdev 来描述

字符设备注册可分为如下3个部分:

1.分配cdev  struct cdev*cdev_alloc(void)

2.初始化cdev cdev_init(struct cedev *p, const struct file_operations *fops)

3. 添加cdev cdev_add(struct cdev *p ,dev_t dev ,unsigned count )  dev设备号设备号的数目

 

字符设备的注销:cdev_dev(structcdev *p)

 

设备操作

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

如果该项为NULL,设备打开永远成功

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

ssize_t (*read)(struct file *, char __user  *buff , size_t , loff_t *)

ssize_t (*write)(struct file *, char __user*, size_t , loff_t *)

file是文件指针(来与内核),*buff是数据缓冲(用户空间),count传输的数据量(用户空间),offp访问位置(来与内核)

*buff是用户空间的,不能直接使用

int copy_from_user(void *to , const void__user *from, int n)

int copy_to_user(void __user *to ,constvoid *to , int n)

loff_t llseek(struct *file ,loff_t offset , int whence)

 

 

open方法主要完成如下工作:1. 初始化设备 2. 标明此设备号

在open(struct inode *inode, struct file *filp)  函数可使用 MINOR(inode->i_rdev;获取此设备号

filp->private_data = dev; 将设备描述指针赋值给私有文件指针 ,区分出了那种设备

 

在read()函数使用struct mem_dev *dev =filp->private_data 可根据私有文件指针指定找到具体的设备,read函数参数没有inode,无法获取此设备号。

 

 

kmalloc分配内存,返回地址,根据其返回的地址就可操作内存中的数据

 

copy_to_user(buf,(void*)(dev->data+p),count)这里的(dev->data+p)为什么要用(void *)强制转换呢?copy_to_user是这么定义的int copy_to_user(void __user*to ,const void *to , int n),但还是不理解。