学习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");