Linux内核设备驱动之字符设备驱动笔记整理

2019-01-16 20:44:33王振洲

////////字符设备驱动//////////

1. 申请设备号

2. 定义一个cdev的设备驱动对象

struct cdev mycdev; //定义一个file_operations的文件操作对象 struct file_operations fops = { .owner = THIS_MODULE, .read = 读函数 .... };

3. 把fops对象与mycdev关联起来

cdev_init(&mycdev, &fops); //mycdev.ops = &fops; mycdev.owner = THIS_MODULE;

4. 把设备驱动加入内核里, 并指定该驱动对应的设备号

cdev_add(&mycdev, 设备号, 次设备号的个数);

5. 卸载模块时, 要把设备驱动从内核里移除, 并把设备号反注册

cdev_del(&mycdev); ///////////创建设备文件 mknod /dev/设备文件名 c 主设备号 次设备号 ////////inode节点对象描述一个文件/设备文件, 包括权限,设备号等信息 struct inode { ... dev_t i_rdev; //设备文件对应的设备号 struct cdev *i_cdev; //指向对应的设备驱动对象的地址 ... }; ////file对象描述文件描述符, 在文件打开时创建, 关闭时销毁 struct file { ... const struct file_operations *f_op; //对应的文件操作对象的地址 unsigned int f_flags; //文件打开的标志 fmode_t f_mode; //权限 loff_t f_pos; //文件描述符的偏移 struct fown_struct f_owner; //属于哪个进程 unsigned int f_uid, f_gid; void *private_data; //给驱动程序员使用 ... };

通file里的成员f_path.dentry->d_inode->i_rdev可以获取到设备文件的设备号

///错误码在<asm/errno.h> ////

/////////struct file_operations ////

inode表示应用程序打开的文件的节点对象,  file表示打开文件获取到的文件描述符

成功返回0, 失败返回错误码

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

buf指向用户进程里的缓冲区, len表示buf的大小(由用户调用read时传进来的)

off表示fl文件描述符的操作偏移, 返回值为实际给用户的数据字节数.

ssize_t (*read) (struct file *fl, char __user *buf, size_t len, loff_t *off);

用户进程把数据给驱动

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

to指用户进程的缓冲区, from指驱动里装数据的缓冲区, n多少字节, 返回值是0

extern inline long copy_to_user(void __user *to, const void *from, long n)

to指驱动的...   from用户...    n多少字节, ....

static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) n = __copy_to_user(to, from, n); return n; //返回值为剩下多少字节没拷贝 }
extern inline long copy_from_user(void *to, const void __user *from, long n)