Dear all,
I'm writing a kernel module and I'd like the module to create a device in /dev/ by itself when loaded (and remove it when unloaded).
Most tutorials I've seen recommend making a script to load the module and use mknod.
I believe it's not possible to use the mknod() system call for obvious reasons, but I also believe there's a way of doing it. Is it a good practice? How to do it?
My best,
Phil
udev
udev was designed to do that. if you use the driver API (struct device or similar) in your module, the device will appear under /sys/ and send events and udev will create a node in /dev/, you just have to create a simple udev rule to name the device.
Dear strcmp, thanks for the
Dear strcmp, thanks for the reply.
I was just trying to figure how to call vfs_mknod() or something like that.
Where can I find some documentation (or examples) on using this API you recommend?
Cheers,
Phil
Documentation/driver-model
there are some documents in the directory Documentation/driver-model in the linux sources
udev
Dear strcmp, thanks again.
I think I've got it. I'm just not sure if I really have to use a driver for udev to work (because it's not working).
I can see my module like this:
root# udevinfo -a -p /sys/module/my_stuff
<...>
looking at device '/module/my_stuff':
KERNEL=="my_stuff"
SUBSYSTEM=="module"
DRIVER==""
ATTR{refcnt}=="0"
ATTR{initstate}=="live"
ATTR{srcversion}=="<...>"
root#
And I've written a rule like this (/etc/udev/rules.d/50-my_stuff.rules):
KERNEL=="my_stuff", SUBSYSTEM=="module", NAME="my_stuff"
(man page for udev says it should pick up these changes automagically, but I've issued a /etc/init.d/udev reload just in case)
And then I load the module with modprobe, but nothing shows up at /dev/
I'm supposing that's because I'm not using a driver?
Thanks for any tip you can provide.
My best,
Phil
Need more general solution than udev only
If you run
find /sys -name devyou will get many hits, such as:
/sys/block/fd0/dev
cat /sys/block/fd0/dev
2:0
means if loading this module, one should also create its device as follows:
mknod /dev/fd0 b 2 0
Your goal should be to make a 'dev' entry appear under /sys for your device and then udev (and mdev in embedded busybox systems) will mknod it automatically.
Making 'dev' appear under /sys
Thanks for the tip, cushioncritter.
Indeed, my module doesn't show a 'dev' entry. However, I've noticed none of the modules do:
root# ls | wc -l
104
root# find . -name dev -print
root#
My module does register itself as follows:
major = register_chrdev(0, "my_stuff", &fops);
And I can confirm major is returning 250 or so (so dynamic allocation is indeed working).
Any ideas on how can I make my module show a 'dev' entry?
Cheers,
Phil
Making 'dev' appear under /sys
I forgot to mention the `ls | wc -l` and the `find` were issued from `/sys/module`.
I still haven't figured how to make this work, so if anyone else has ideas, I'd appreciate.
Cheers,
Phil
Making 'dev' appear under /sys
If your driver is of a known class (such as block) and you register it properly the node will appear automatically as udev already knows the rules. If it is a new "class" then you have to either fiddle with the udev rules in user space or define a new class of your own; for instance on loading your driver you could do:
static struct class *fc;
fc=class_create(THIS_MODULE, "my_class");
device_create(fc,NULL,first,"%s","mydrv");
which would create /dev/mydrv
On unload do:
device_destroy(fc,first);
class_destroy(fc);
(first is the major/minor dev_t quantity).
Read the API for the "class"
functions.
Hope this helps