设备驱动之一 - proc文件系统接口

来源:互联网 发布:coc九本女王升级数据 编辑:程序博客网 时间:2024/05/21 14:57

      学习linux设备驱动,第四章;

      关于proc文件系统接口编程参见

      procfs读取信息实例:http://blog.csdn.net/iamonlyme/article/details/7062237

      procfs读写信息实例:http://blog.csdn.net/iamonlyme/article/details/7065243

本次修改的代码是属于main.c函数,主要是增加proc接口实现代码

/********************************************** * Author: lewiyon@hotmail.com * File name: scullmod.c  * Description: initialize and release function for scull * Date: 2012-07-4 *********************************************/#include <linux/init.h>         /* module        */#include <linux/module.h>       /* module        */#include <linux/moduleparam.h>  /* module        */#include <linux/errno.h>        /* error codes   */#include <linux/kernel.h>       /* printk        */#include <linux/slab.h>         /* kmalloc kfree */#include <linux/types.h>        /* dev_t         */#include <linux/proc_fs.h>      /* dev_t         *//* local head files */#include "scull.h"#include "file.h"#define SCULL_PROC_NAME "scull"   /* default parameters of module */int scull_major = SCULL_MAJOR;int scull_minor = 0;int scull_nr_devs = SCULL_NR_DEVS;int scull_quantum = SCULL_QUANTUM;int scull_qset = SCULL_QSET;/* input parameters of module */module_param(scull_major, int, S_IRUGO);module_param(scull_minor, int, S_IRUGO);module_param(scull_nr_devs, int, S_IRUGO);module_param(scull_quantum, int, S_IRUGO);module_param(scull_qset, int, S_IRUGO);struct scull_dev *scull_devices;static struct proc_dir_entry *scull_proc;  static struct proc_dir_entry *scull_info; int scull_read_procmem(char *buf, char **start, off_t offset,        int count, int *eof, void *data){    int len;    struct scull_dev *dev;    len = 0;    dev = scull_devices;    if (down_interruptible(&dev->sem))        return -ERESTARTSYS;   len += sprintf(buf + len, "qset:%i\nquantum:%i\nsize:%li\n",            dev->qset, dev->quantum, dev->size);    up(&dev->sem);    *eof = 1;    return len;}/* * scull_trim -  遍历链表,并释放所有找到的量子和量子集 * @dev: scull设备 */int scull_trim(struct scull_dev *dev){    int i, qset;    struct scull_qset *next, *dptr;        qset = dev->qset;    for (dptr = dev->data; dptr; dptr = next) {        if (dptr->data) {            for (i = 0; i < qset; i++)                kfree(dptr->data[i]);            kfree(dptr->data);            dptr->data = NULL;        }        next = dptr->next;        kfree(dptr);    }    dev->size = 0;    dev->quantum = scull_quantum;    dev->qset = scull_qset;    dev->data = NULL;    return 0;}static void scull_setup_cdev(struct scull_dev *dev, int index){    int err;    int devno;    devno = MKDEV(scull_major, scull_minor + index);    cdev_init(&dev->cdev, &scull_fops);    dev->cdev.owner = THIS_MODULE;    dev->cdev.ops = &scull_fops;       err = cdev_add(&dev->cdev, devno, 1);    if (err)         printk(KERN_NOTICE "Error %d adding scull%d", err, index);   }static void scull_unregister(void){    int i;    dev_t devno;    devno = MKDEV(scull_major, scull_minor);    /* delete each entry */    if (scull_devices) {        for (i = 0; i < scull_nr_devs; i++) {            scull_trim(scull_devices + i);            cdev_del(&scull_devices[i].cdev);        }        kfree(scull_devices);    }    /* unregister */    unregister_chrdev_region(devno, scull_nr_devs);}/* * initialze scull module  */void scull_cleanup_module(void){    remove_proc_entry("scullmem", scull_proc);    remove_proc_entry(SCULL_PROC_NAME, NULL);    scull_unregister();    printk(KERN_WARNING "scull: Bye!\n");}/* * initialze scull module  */int scull_init_module(void){    int i, res;    dev_t dev = 0;        if (scull_major) {        dev = MKDEV(scull_major, scull_minor);        res = register_chrdev_region(dev, scull_nr_devs, "scull");    } else {        res = alloc_chrdev_region(&dev, scull_minor,                 scull_nr_devs, "scull");        scull_major = MAJOR(dev);    }    if (res < 0) {        printk(KERN_WARNING "scull: can't get major %d\n", scull_major);        return res;    }    /*      * allocate the device struct cache     */    scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev),             GFP_KERNEL);    if (NULL == scull_devices) {        res = -ENOMEM;        printk(KERN_WARNING "scull: NOMEM for scull!\n");        goto fail;    }    memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));    /* initialize each device */    for (i = 0; i < scull_nr_devs; i++) {        scull_devices[i].quantum = scull_quantum;        scull_devices[i].qset = scull_qset;        sema_init(&scull_devices[i].sem, 1);        scull_setup_cdev(&scull_devices[i], i);    }    printk(KERN_INFO "scull: OK!\n");    scull_proc = proc_mkdir(SCULL_PROC_NAME, NULL);    if (NULL == scull_proc)     {         res = -ENOMEM;            goto fail;    }    scull_info = create_proc_read_entry("scullmem", 0, scull_proc,             scull_read_procmem, NULL);    if (NULL == scull_info)    {        res = -ENOMEM;        goto info_err;    }    printk(KERN_INFO "scull proc: OK!\n");    return 0;info_err:    remove_proc_entry(SCULL_PROC_NAME, NULL);fail:    scull_unregister();    return res;}module_init(scull_init_module);module_exit(scull_cleanup_module);MODULE_AUTHOR("lewiyon@hotmail.com");MODULE_LICENSE("GPL");