2

here is dumb chardevice lkm:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>

MODULE_AUTHOR ("milo");
MODULE_DESCRIPTION ("alloc_chrdev_troubleshooting");
MODULE_LICENSE("GPL");
static int devmajor = 0;
static char * devname = "chardev_alloc";

static int setup_chardevice(void) {
    int result;
    dev_t dev;
    result = alloc_chrdev_region(&dev, 0, 1, devname);
    if (result < 0) {
        return result;
    }
    printk(KERN_INFO "major is %d", MAJOR(dev));
    devmajor = MAJOR(dev);
    devmajor = result;
    return 0;
};

void delete_chardevice(void) {
    unregister_chrdev_region(MKDEV(devmajor, 0), 1);
};

static int __init test_init(void) {
    int res;
    res = setup_chardevice();
    if (res) {
        printk(KERN_ERR "couldn't setup chardevice, goodbye.");
        return res;
    }
    printk(KERN_WARNING "chardevice test driver is loaded");
    return 0;   
}
static void __exit test_cleanup(void) {
    delete_chardevice();
    printk(KERN_WARNING "chardevice test driver is unloading");
    return;
}

module_init(test_init);
module_exit(test_cleanup);

after doing rmmod major device number is not deallocated and i can see it in /proc/devices. it is really annoying... Here is Makefile for quick test:

KDIR ?= /lib/modules/`uname -r`/build
obj-m += chartest.o
chartest-objs := main.o
default: all
modules:
    $(MAKE) -C $(KDIR) M=$(PWD) modules
modules_clean:
    $(MAKE) -C $(KDIR) M=$(PWD) clean
all: modules
clean: modules_clean

what did i do wrong? please, suggest.

milo
  • 1,220
  • 3
  • 17
  • 33

1 Answers1

3
devmajor = MAJOR(dev);
devmajor = result;

You are overwriting the devmajor variable with the return value of alloc_chrdev_region() alloc_chrdev_region() returns 0 on success, not the major number.

You are then attempting to release device MKDEV(devmajor, 0), which is probably MKDEV(0, 0) if alloc_chrdev_region succeeded, instead of your device.

Lifesworder
  • 110
  • 1
  • 5