1. 程式人生 > >21 型別的封裝(核心裡的繼承)

21 型別的封裝(核心裡的繼承)

型別的封裝(核心裡的繼承)


#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <asm/uaccess.h>

#define MYMA  1234
#define MYMI  7788
#define COUNT 1

//為了方便重用和維護,把驅動所用到的資料封裝成一個型別
typedef struct {
    dev_t devid;
    struct
cdev mycdev; u8 *data; //驅動資料緩衝區 int dlen; //驅動資料緩衝區長度 }mydev_t; ssize_t myread(struct file *fl, char __user *buf, size_t len, loff_t *off) { struct cdev *cdev = fl->f_path.dentry->d_inode->i_cdev; //這裡可能得到mydev_t物件的mycdev成員地址 mydev_t *dev = container_of(cdev, mydev_t, mycdev); //通過mycdev成員的地址得到mydev_t物件的首地址
int len_copy, ret; if ((fl->f_pos + len) > strlen(dev->data)) len_copy = strlen(dev->data) - fl->f_pos; else len_copy = len; ret = copy_to_user(buf, dev->data+fl->f_pos, len_copy); *off += len_copy - ret; return len_copy - ret; } struct
file_operations fops = { .owner = THIS_MODULE, .read = myread, }; mydev_t *dev; static int __init test_init(void) { int ret, i; dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev->devid = MKDEV(MYMA, MYMI); ret = register_chrdev_region(dev->devid, COUNT, "mydev"); if (ret < 0) goto err0; cdev_init(&(dev->mycdev), &fops); dev->mycdev.owner = THIS_MODULE; ret = cdev_add(&(dev->mycdev), dev->devid, COUNT); if (ret < 0) goto err1; dev->dlen = 26; dev->data = kzalloc(dev->dlen, GFP_KERNEL); for (i = 0; i < 26; i++) dev->data[i] = 'A' + i; return 0; err1: unregister_chrdev_region(dev->devid, COUNT); err0: return ret; } static void __exit test_exit(void) { unregister_chrdev_region(dev->devid, COUNT); cdev_del(&(dev->mycdev)); kfree(dev->data); kfree(dev); } module_init(test_init); module_exit(test_exit); MODULE_LICENSE("GPL");