Opening a device file fails due to No such device or address

srik picture srik · Oct 13, 2016 · Viewed 13.5k times · Source

I am trying to create a character device driver (kernel module). The modue gets loaded, creates the character device as can be seen below:

    root@imx6x-std:~# ls -l /dev/socledchrdevregion
crw-rw-rw-    1 root     root      246,   0 Jan  1 08:56 /dev/socledchrdevregion

But when i try to open the device using a test application (the open function inside the driver doesn't do anything special apart from printing a debug message), i get an error:

root@imx6x-std:~# ./led_ioctltest
led_ioctltest: open /dev/socledchrdevregion failed due to No such device or addres

Following is the content of /proc/devices:

    root@imx6x-std:~# cat /proc/devices
Character devices:
  1 mem
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
 10 misc
 13 input
 29 fb
 81 video4linux
 89 i2c
 90 mtd
116 alsa
128 ptm
136 pts
153 spi
180 usb
189 usb_device
199 galcore
207 ttymxc
244 vuc_sim
245 vuc
246 socledchrdevregion
247 ubi0
248 mxc_src
249 mxc_vpu
250 conti_kmod_tracing
251 mxc_ipu
252 ptp
253 pps
254 rtc

Block devices:
259 blkext
 31 mtdblock
179 mmc

The device is present with major number is 246.

This is the way i try to open the device:

 #define DEVICE "/dev/socledchrdevregion"
fd = open(DEVICE, O_RDONLY);

This is a snippet of the LKM:

if ((ret = alloc_chrdev_region(&first, 0, 1, DEVICE_NAME)) < 0)
{
        printk(KERN_ERR PRINTK_CONTEXT": FAILED TO ALLOCATE CHRDEVREGION \n");
        return -1;
}

printk(KERN_INFO PRINTK_CONTEXT": ALLOCATE CHRDEVREGION SUCCESS \n");

classptr = class_create(THIS_MODULE, "socledclass");
device_create(classptr, NULL, first, NULL, DEVICE_NAME);
printk(KERN_INFO "PRINTK_CONTEXT: DEVICE CREATED \n");
led_cdevptr = cdev_alloc();
led_cdevptr->ops = &led_fops;

Could anyone please help me in finding the error? I will post the complete code if necessary.

Answer

Shachar Shemesh picture Shachar Shemesh · Oct 15, 2016

You have registered your device with sysfs, which causes it to become visible (and for udev to create the device file). You did not, however, register the actual device. You got a major minor assigned, but they are not connected to your driver.

In all likelihood, you have skipped calling cdev_add.

In a nutshell, the sequence is: alloc_chrdev_region gives you a range of major/minor device IDs you can use, that are guaranteed to be only for your device.

cdev_add register actual handlers for those IDs (you can call it without calling alloc_chrdev_region if your device has a preallocated region set to it, such as /dev/null or /dev/random).