悲剧了...卸载模块之后/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]