分享

最简单的字符设备驱动程序

 北漂之邬 2014-01-23

首先,先理清一下简单字符设备驱动程序的思路:

(1)申请设备号

      动态申请:int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)

      静态申请:int register_chrdev_region(dev_t from,  unsigned count, const char *name)

      成功返回0,失败返回负数,并置于errno

(2)分配cdev ,可以使用struct cdev *cdev_alloc(void) ,或者静态定义全局cdev变量

(3)初始化cdev

       若使用动态分配,则需要进行初始化:void cdev_init(struct cdev *cdev, const struct file_operations *fops)  ,mem_cdev.owner = THIS_MODULE;

       若动态内存定义初始化:struct cdev *mem_cdev = cdev_alloc();    mem_cdev->ops = &fops;   mem_cdev->owner = THIS_MODULE

(4)添加cdev

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

若使用内存模拟字符设备,则还需申请空间:

     mem_devp = kmalloc( 2 * sizeof(struct mem_dev), GFP_KERNEL);
        if(!mem_devp){
                result = -ENOMEM;
                goto fail_malloc;
        }
        memset(mem_devp, 0, sizeof(struct mem_dev));
        for(i = 0; i < 2; i++)
        {
                mem_devp[i].size = MEMDEV_SIZE;
                mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);
                memset(mem_devp[i].data, 0, MEMDEV_SIZE);
        }

申请失败情况下,记得注销设备号,使用void unregister_chrdev_region(dev_t from, unsigned count)

(5)构造file_operations结构体(结构体字段的初始化)

static const struct file_operations mem_fops =
{
        .owner = THIS_MODULE,
        .llseek = mem_llseek,
        .read = mem_read,
        .write = mem_write,
        .open = mem_open,
        .release = mem_release,
};

(6)实现file_operations支持的函数

 int mem_open(struct inode *inode, struct file *filp)
{
        struct mem_dev *dev;
        int num = MINOR(inode->i_rdev);
        if(num >= MEMDEV_NR_DEVS)
                return -ENODEV;
        dev = &mem_devp[num];
        filp->private_data = dev;

        return 0;
}

static ssize_t mem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
        unsigned long p = *ppos;
        unsigned int count = size;
        int ret = 0;
        struct mem_dev *dev = filp->private_data;
        if(p > MEMDEV_SIZE)
                return 0;
        if(count > MEMDEV_SIZE - p)
                count = MEMDEV_SIZE - p;
        if(copy_to_user(buf, (void *)(dev->data + p), count)){
        ret = -EFAULT;
        }
        else{
        *ppos += count;
        ret = count;
        printk(KERN_INFO "read %d bytes from %ld", count, p);
        }
        return ret;
}
static ssize_t mem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
        unsigned long p = *ppos;
        unsigned int count = size;
        int ret = 0;
        struct mem_dev *dev = filp->private_data;
        if(p > MEMDEV_SIZE)
                return 0;
        if(count > MEMDEV_SIZE - p)
                count = MEMDEV_SIZE - p;
        if(copy_from_user(dev->data + p, buf, count)){
        ret = -EFAULT;
        }
        else{
        *ppos += count;
        ret = count;
        printk(KERN_INFO "writen %d bytes from %ld", count, p);
        }
        return ret;
}

static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)
{
        loff_t newpos;
        switch(whence){
                case 0:
                  newpos = offset;
                  break;
                case 1:
                  newpos = filp->f_pos+offset;
                  break;
                case 2:
                  newpos = MEMDEV_SIZE - 1 + offset;
                  break;
                default:
                  return -EINVAL;
        }
        if((newpos < 0) || (newpos > MEMDEV_SIZE))
                return -EINVAL;
        filp->f_pos = newpos;
        return newpos;
}

int mem_release(struct inode *inode, struct file *filp)
{
        return 0;
}

测试代码:

#include <stdio.h>

int main()
{
        FILE *fp = NULL;
        char Buf[4096];

        strcpy(Buf, "mem is char dev!");
        printf("Buf:%s\n",Buf);

        fp = fopen("/dev/memdev1", "r+");
        if(fp == NULL){
        printf("open memdev1 error!\n");
        }

        fwrite(Buf, sizeof(Buf), 1, fp);
        fseek(fp, 0, SEEK_SET);

        strcpy(Buf,"Buf is NULL!");
        printf("Buf: %s\n",Buf);

        fread(Buf, sizeof(Buf), 1, fp);
        printf("Buf: %s\n",Buf);
        return 0;
}

 

 


  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多