PCliangtao 发表于 2010-09-20 17:14

悲剧了...卸载模块之后/proc/devices下创建的入口还存在...

小弟正在学习设备驱动程序...不料... 把加载模块和卸载模块的部分写了一下.. 然后编译成模块... 想试试写的是否正确.. 然后在逐渐添加方法...结果...
   insmod module.ko之后在/proc/module下能发现加载的模块. 在/proc/devices下也能发现device name。这表示正确的加载并且初始化了...
   可是rmmod能够把模块卸载... 但是/proc/devices/device_name仍然存在...不晓得为什么... 求解...
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fcntl.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/errno.h>

struct ram_device {
        unsigned long size;
        char *data;
        short usage;
        short midea_changed;
        spinlock_t lock;
        struct request_queue *queue;
        struct gendisk *disk;
};

#define DEF_RAM_SIZE 4096000UL
#define DEF_RAM_MAJOR 0
#define DEF_RAM_MINOR 4
#define DEF_RAM_HARDSECTOR 512UL
#define KERNEL_HARDSECTOR 512UL
#define DEVICE_NAME "ram_block_device"

static unsigned long ram_size = DEF_RAM_SIZE;
static int ram_major = DEF_RAM_MAJOR;
static int ram_minor = DEF_RAM_MINOR;
static unsigned long ram_hardsector = DEF_RAM_HARDSECTOR;
//module_param(ram_size, unsigned long, DEF_RAM_SIZE);
//module_param(ram_major, int, DEF_RAM_MAJOR);
//module_param(ram_minor, int, DEF_RAM_MINOR);
//module_param(ram_hardsector, unsigned long, DEF_RAM_HARDSECTOR);
static struct ram_device *ram_dev;

static void ram_trans(struct ram_device *dev, unsigned long start_sector, unsigned long nr_sector, char *buffer, int rw)
{
        unsigned long offset = start_sector * KERNEL_HARDSECTOR;
        unsigned long nbytes = nr_sector * KERNEL_HARDSECTOR;
        char *start = dev->data + offset;
        if((offset + nbytes) > dev->size) {
                printk(KERN_NOTICE "over bound : offset %ld, nbytes %ld\n", offset, nbytes);
                return;
        }
        if(rw)
                memcpy(start, buffer, nbytes);
        else
                memcpy(buffer, start, nbytes);
}

static void ram_request(request_queue_t *q)
{
        struct request *req;
        while(!(req = elv_next_request(q))) {
                struct ram_device *dev = req->rq_disk->private_data;
                if(!blk_fs_request(req)) {
                        end_request(req, 0);
                        continue;
                }
                ram_trans(dev, req->sector, req->current_nr_sectors, req->buffer, rq_data_dir(req));
                end_request(req, 1);
        }
}


static int ram_device_init(void)
{
        int retval = -EBUSY;
        ram_major = register_blkdev(ram_major, DEVICE_NAME);
        if(ram_major < 0)
                goto out;
        retval = -ENOMEM;
        ram_dev = kmalloc(sizeof(struct ram_device), GFP_KERNEL);
        if(!ram_dev)
                goto unregister;
        memset(ram_dev, 0, sizeof(struct ram_device));
        ram_dev->size = ram_size;
        ram_size &= (~4095);
        if(!ram_size)
                goto unregister;
        ram_dev->data = vmalloc(ram_size);
        if(!ram_dev->data)
                goto unregister;
        spin_lock_init(&ram_dev->lock);
       
/* initialize request queue and bind request function */
        ram_dev->queue = blk_init_queue(ram_request, &ram_dev->lock);
        if(!ram_dev->queue)
                goto free;
        ram_dev->queue->queuedata = ram_dev;
        blk_queue_hardsect_size(ram_dev->queue, ram_hardsector);
/* allocate a gendisk struct and initialize some fields that we're interested in */
        ram_dev->disk = alloc_disk(ram_minor);
        if(!ram_dev->disk)
                goto free;
        ram_dev->disk->major = ram_major;
        ram_dev->disk->first_minor = 0;
//        ram_dev->disk->fops = &ram_ops;
        ram_dev->disk->queue = ram_dev->queue;
        ram_dev->disk->private_data = ram_dev;
        sprintf(ram_dev->disk->disk_name, DEVICE_NAME);
        set_capacity(ram_dev->disk, (ram_size / KERNEL_HARDSECTOR));
/* register it*/
        add_disk(ram_dev->disk);
        return 0;
free:
                vfree(ram_dev->data);
unregister:
        unregister_blkdev(ram_major, DEVICE_NAME);
out:
        return retval;
}

static void ram_device_exit(void)
{
        if(ram_dev && ram_dev->disk) {
                del_gendisk(ram_dev->disk);
                put_disk(ram_dev->disk);
        }
        if(ram_dev->queue)
                blk_cleanup_queue(ram_dev->queue);
        if(ram_dev->data)
                vfree(ram_dev->data);
        kfree(ram_dev);
        unregister_blkdev(ram_major, DEVICE_NAME);
}

module_init(ram_device_init);
module_exit(ram_device_exit);

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

页: [1]
查看完整版本: 悲剧了...卸载模块之后/proc/devices下创建的入口还存在...