天天看點

linux核心字元裝置驅動相關的函數以及結構體

 1. struct cdev {

         struct kobject kobj;

         struct module *owner;

         const struct file_operations *ops;

         struct list_head list;

         dev_t dev;

         unsigned int count;

};//描述字元裝置

2. void cdev_init(struct cdev *cdev, const struct file_operations *fops){

         memset(cdev, 0, sizeof *cdev);

         INIT_LIST_HEAD(&cdev->list);

         cdev->kobj.ktype = &ktype_cdev_default;

         kobject_init(&cdev->kobj);

         cdev->ops = fops;

}//用于初始化cdev的成員,并建立cdev和file_operations之間的連結

3. struct cdev *cdev_alloc(void){

         struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);

         if (p) {

                   p->kobj.ktype = &ktype_cdev_dynamic;

                   INIT_LIST_HEAD(&p->list);

                   kobject_init(&p->kobj);

         }

         return p;

}//用于動态申請一個cdev記憶體

4.int cdev_add(struct cdev *p, dev_t dev, unsigned count){

         p->dev = dev;

         p->count = count;

         return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);

}//添加(注冊)一個cdev

5. void cdev_del(struct cdev *p){

         cdev_unmap(p->dev, p->count);

         kobject_put(&p->kobj);

}//删除(登出)一個cdev

6. MAJOR(dev_t dev)//得到主裝置号

7.MINOR(dev_t dev)//得到次裝置号

8. MKDEV(int major,int minor)//生成dev_t

9. int register_chrdev_region(dev_t from, unsigned count, const char *name){

         struct char_device_struct *cd;

         dev_t to = from + count;

         dev_t n, next;

         for (n = from; n < to; n = next) {

                   next = MKDEV(MAJOR(n)+1, 0);

                   if (next > to)

                            next = to;

                   cd = __register_chrdev_region(MAJOR(n), MINOR(n),

                                   next - n, name);

                   if (IS_ERR(cd))

                            goto fail;

         }

         return 0;

fail:

         to = n;

         for (n = from; n < to; n = next) {

                   next = MKDEV(MAJOR(n)+1, 0);

                   kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));

         }

         return PTR_ERR(cd);

}//向系統申請裝置号,已知起始裝置的裝置号

10.int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,

                            const char *name){

         struct char_device_struct *cd;

         cd = __register_chrdev_region(0, baseminor, count, name);

         if (IS_ERR(cd))

                   return PTR_ERR(cd);

         *dev = MKDEV(cd->major, cd->baseminor);

         return 0;

}//向系統申請裝置号,裝置号未知,向系統申請未被暫用的裝置号

11.void unregister_chrdev_region(dev_t from, unsigned count){

         dev_t to = from + count;

         dev_t n, next;

         for (n = from; n < to; n = next) {

                   next = MKDEV(MAJOR(n)+1, 0);

                   if (next > to)

                            next = to;

                   kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));

         }

}//釋放申請的裝置号

12. 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 *);

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

         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 *, struct dentry *, 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 (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);

         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 (*dir_notify)(struct file *filp, unsigned long arg);

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

};//結構體中的成員函數是字元裝置驅動程式設計的主體内容

由于字元裝置的上層沒有磁盤檔案系統,是以字元裝置的file_operations成員函數就直接由裝置驅動提供了,file_operations正是字元裝置驅動的核心。

字元裝置驅動子產品加載

想要實作一個驅動子產品的加載至少應該實作以下幾個步驟:

1.       對裝置進行初始化

2.       擷取裝置号

3.       添加(注冊)裝置

字元裝置驅動子產品解除安裝

驅動子產品的解除安裝至少應該實作以下幾個步驟:

1.       釋放占用的裝置号

2.       删除(登出)裝置

繼續閱讀