character_device.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /*
  2. Allows us to create device files with given file operations with mknod c X.
  3. Usage:
  4. /character_device.sh
  5. The major number determines which module owns the device file.
  6. minor is to differentiate between multiple instances of the device,
  7. e.g. two NVIDIA GPUs using the same kernel module.
  8. We ask the kernel to automatically allocate a major number for us to avoid
  9. conlicts with other devices.
  10. Then we need to check /proc/devices to find out the assigned number,
  11. and use that for the mknod.
  12. - https://unix.stackexchange.com/questions/37829/understanding-character-device-or-character-special-files/371758#371758
  13. */
  14. #include <asm/uaccess.h> /* copy_from_user, copy_to_user */
  15. #include <linux/errno.h> /* EFAULT */
  16. #include <linux/fs.h> /* register_chrdev, unregister_chrdev */
  17. #include <linux/jiffies.h>
  18. #include <linux/module.h>
  19. #include <linux/printk.h> /* printk */
  20. #include <uapi/linux/stat.h> /* S_IRUSR */
  21. #define NAME "lkmc_character_device"
  22. MODULE_LICENSE("GPL");
  23. static int major;
  24. static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off)
  25. {
  26. size_t ret;
  27. char kbuf[] = {'a', 'b', 'c', 'd'};
  28. ret = 0;
  29. if (*off == 0) {
  30. if (copy_to_user(buf, kbuf, sizeof(kbuf))) {
  31. ret = -EFAULT;
  32. } else {
  33. ret = sizeof(kbuf);
  34. *off = 1;
  35. }
  36. }
  37. return ret;
  38. }
  39. static const struct file_operations fops = {
  40. .owner = THIS_MODULE,
  41. .read = read,
  42. };
  43. static int myinit(void)
  44. {
  45. major = register_chrdev(0, NAME, &fops);
  46. return 0;
  47. }
  48. static void myexit(void)
  49. {
  50. unregister_chrdev(major, NAME);
  51. }
  52. module_init(myinit)
  53. module_exit(myexit)