《Linux设备驱动程序》读书笔记:字符设备驱动程序(一)

来源:互联网 发布:淘宝联盟官网 编辑:程序博客网 时间:2024/05/17 06:26

看不容易抽点空下来看书,现在留点痕迹吧!

一:创建设备类型

      四个全局持久的字符设备scull0-scull3

二:主次设备号

     主设备号:代表设备类型

     次设备号 : 一个编号

     MAJOR(dev_t dev)

     MINOR(dev_t dev)

     MKDEV(int major, int minor)

     注册释放

     register_chrdev_region

     alloc_chrdev_region

     unregister_chrdev_region


三: file_operations

     

struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);int (*readdir) (struct file *, void *, filldir_t);unsigned int (*poll) (struct file *, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);int (*open) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*release) (struct inode *, struct file *);int (*fsync) (struct file *, loff_t, loff_t, int datasync);int (*aio_fsync) (struct kiocb *, int datasync);int (*fasync) (int, struct file *, int);int (*lock) (struct file *, int, struct file_lock *);ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);int (*check_flags)(int);int (*flock) (struct file *, int, struct file_lock *);ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);int (*setlease)(struct file *, long, struct file_lock **);long (*fallocate)(struct file *file, int mode, loff_t offset,  loff_t len);};

实例化

struct file_operations scull_fops = {.owner =    THIS_MODULE,.llseek =   scull_llseek, //移位.read =     scull_read, //读.write =    scull_write, //写.ioctl =    scull_ioctl, //ioctrl.open =     scull_open, //打开.release =  scull_release, //释放};

注意scull_open函数, 里面使用了一个C语言的技巧:

container_of
通过结构体成员的地位获取结构体实例的地址(原理在于通过地址0算出成员的偏移再相减,注意里面要将地址转成char*类型, 和UEFI里的宏CR一样)

#define container_of(ptr, type, member) ({\const typeof( ((type *)0)->member ) *__mptr = (ptr);\(type *)( (char *)__mptr - offsetof(type,member) );})


int scull_open(struct inode *inode, struct file *filp){struct scull_dev *dev; /* device information */dev = container_of(inode->i_cdev, struct scull_dev, cdev);filp->private_data = dev; /* for other methods */ //注意:private_data在open时可以保存设备指针/* now trim to 0 the length of the device if open was write-only */if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) {if (down_interruptible(&dev->sem))return -ERESTARTSYS;scull_trim(dev); /* ignore errors */up(&dev->sem);}return 0;          /* success */}



四: 内核struct file

     注意:private_data在open时可以保存设备指针


五 : 内存组织

struct scull_dev {struct scull_qset *data;  /* Pointer to first quantum set */int quantum;              /* the current quantum size */int qset;                 /* the current array size */unsigned long size;       /* amount of data stored here */unsigned int access_key;  /* used by sculluid and scullpriv */struct semaphore sem;     /* mutual exclusion semaphore     */struct cdev cdev;  /* Char device structure*/};struct scull_qset {void **data;struct scull_qset *next;};


原创粉丝点击