• 字符驱动开发2


    前面一篇文章,自己记录了字符设备开发。实现内存数据的读写,但是有个问题,设备的创建,需要依靠手动的mknod来创建,有没有改进,直接加载驱动,
    就可以完成设备的自动创建了,这里增加了class_create的创建,实现驱动的加载和设备创建,同步触发。对应平台性的设备来说,这样的创建,也是可以接受的。
    代码附录如下:

    include <linux/module.h>

    include <linux/types.h>

    include <linux/fs.h>

    include <linux/errno.h>

    include <linux/mm.h>

    include <linux/sched.h>

    include <linux/init.h>

    include <linux/cdev.h>

    include <linux/uaccess.h>

    include<linux/slab.h>

    define GLOBAMEM_SIZE 0x1000

    define MEM_CLEAR 0X1

    define GLOBALMEM_MAJOR 0

    define INSMOD_CREATE_DEV

    static int globalmem_major = GLOBALMEM_MAJOR;
    static struct class *gmem_class;

    /* globalmem设备结构体 */
    struct globalmem_dev {
    struct cdev cdev;
    unsigned char mem[GLOBAMEM_SIZE];
    };

    struct globalmem_dev globalmem_devp;
    /
    文件打开函数 */
    int globalmem_open(struct inode *inode, struct file filp)
    {
    /
    /
    filp->private_data = globalmem_devp;
    return 0;
    }
    /
    文件释放函数 */
    int globalmem_release(struct inode *inode, struct file *filp)
    {
    return 0;
    }

    /* ioctl 设备控制函数 */
    static long globalmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
    //
    struct globalmem_dev dev = filp->private_data;/ 获得设备结构体指针 */

    switch (cmd){
    case MEM_CLEAR:
    	memset(dev->mem, 0, GLOBAMEM_SIZE);
    	printk(KERN_INFO "globalmem is set to zero\n");
    	break;
    
    default:
    	return - EINVAL;
    }
    
    return 0;
    

    }

    /* 读函数 */
    static ssize_t globalmem_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 globalmem_dev *dev = filp->private_data;/* 获得设备结构体指针 */ 
    
    
    if (p >= GLOBAMEM_SIZE)
    	return 0;
    if (count > GLOBAMEM_SIZE - p)
    	count = GLOBAMEM_SIZE - p;
    
    /* 内核空间--> 用户空间 */
    if (copy_to_user(buf, (void *)(dev->mem + p), count)) {
    	ret = EFAULT;
    }else {
    	*ppos += count;
    	ret = count;
    
    	printk(KERN_INFO "read %u bytes(s) from %lu\n", count, p);
    }
    
    return ret;
    

    }
    static ssize_t globalmem_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 globalmem_dev *dev = filp->private_data;/* 获得设备结构体指针 */ 
    
    
    if (p >= GLOBAMEM_SIZE)
    	return 0;
    if (count > GLOBAMEM_SIZE - p)
    	count = GLOBAMEM_SIZE - p;
    
    /* 用户空间--> 内核空间 */
    if (copy_from_user((void *)(dev->mem + p), buf,count)) {
    	ret = EFAULT;
    }else {
    	*ppos += count;
    	ret = count;
    
    	printk(KERN_INFO "write %u bytes(s) from %lu\n", count, p);
    }
    
    return ret;
    

    }
    static loff_t globalmem_llseek(struct file *filp, loff_t offset,int orig)
    {

    int ret = 0;
    struct globalmem_dev *dev = filp->private_data;/* 获得设备结构体指针 */ 
    
    
    
    return ret;
    

    }
    /* 文件操作结构体 */
    static const struct file_operations globalmem_fops = {
    .owner = THIS_MODULE,
    .llseek = globalmem_llseek,
    .read = globalmem_read,
    .write = globalmem_write,
    .unlocked_ioctl = globalmem_ioctl,
    .open = globalmem_open,
    .release = globalmem_release,
    };

    /* 初始化并注册cdev */
    static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)
    {
    int err, devno = MKDEV(globalmem_major, index);
    cdev_init(&dev->cdev, &globalmem_fops);
    dev->cdev.owner = THIS_MODULE;
    err = cdev_add(&dev->cdev, devno, 1);
    if (err)
    printk(KERN_NOTICE "Error %d adding globalmem %d", err, index);
    }

    /* 设备驱动模块加载函数 */
    int globalmem_init(void)
    {

    ifdef INSMOD_CREATE_DEV

    globalmem_major = register_chrdev(0, "gmem", &globalmem_fops);
    gmem_class = class_create(THIS_MODULE,"gmem");
    device_create(gmem_class, NULL, MKDEV(globalmem_major, 0), NULL, "mgem"); /* /dev/led */
    globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
    if (!globalmem_devp) { /* 申请失败 */
    	printk(KERN_NOTICE "Error kmalloc failed");
    }
    return 0;
    

    else

    int result;
    dev_t devno = MKDEV(globalmem_major, 0);   /*   devno = (250<<20) | 0   */
    
    /* 申请设备号 */
    if (globalmem_major)
    	result = register_chrdev_region(devno, 1, "globalmem");
    else { /* 动态申请设备号 */
    	result = alloc_chrdev_region(&devno, 0, 1, "globalmem");
    	globalmem_major = MAJOR(devno);
    }
    if (result < 0)
    	return result;
    
    /* 动态申请设备结构体的内存 */
    globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
    if (!globalmem_devp) { /* 申请失败 */
    	result = - ENOMEM;
    	goto fail_malloc;
    }
    
    memset (globalmem_devp, 0, sizeof(struct globalmem_dev));
    
    globalmem_setup_cdev(globalmem_devp, 0);
    
    return 0;
    

    fail_malloc:
    unregister_chrdev_region(devno, 1);
    return result;

    endif

    }

    /* 模块卸载函数 */
    void globalmem_exit(void)
    {

    ifdef INSMOD_CREATE_DEV

    unregister_chrdev(globalmem_major, "gmem");
    device_destroy(gmem_class,  MKDEV(globalmem_major, 0));
    class_destroy(gmem_class);
    

    else

    cdev_del(&globalmem_devp->cdev);	/* 注销CDEV */
    kfree(globalmem_devp); /* 释放设备结构体内存 */
    
    unregister_chrdev_region(MKDEV(globalmem_major, 0), 1); /* 释放设备号 */
    

    endif

    }

    MODULE_AUTHOR("Fourier");
    MODULE_LICENSE("Dual BSD/GPL");

    module_param(globalmem_major, int, S_IRUGO);

    module_init(globalmem_init);
    module_exit(globalmem_exit);

  • 相关阅读:
    Android 锁屏 临时屏蔽
    单编译framework相关模块
    02
    pad 强制加载 Hdpi资源 (2.3 dpi < 240)
    设置form的默认按钮
    How to Be a Good Graduate Student
    我怕你们急于求成
    希腊字母读音表
    数据库札记(二)
    Ubuntu 9.04下jdk的安装与配置
  • 原文地址:https://www.cnblogs.com/gaoshanxiaolu/p/16288861.html
Copyright © 2020-2023  润新知