Advertisement
xosski

Character device driver emulation

Jan 9th, 2025
7
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.39 KB | None | 0 0
  1. #include <linux/module.h>
  2. #include <linux/fs.h>
  3. #include <linux/cdev.h>
  4. #include <linux/device.h>
  5. #include <linux/uaccess.h>
  6. #include <linux/slab.h>
  7. #include <linux/mutex.h>
  8.  
  9. #define NUM_MINORS 5
  10. #define BUFFER_SIZE 100
  11.  
  12. static dev_t dev_num; // Holds major and minor numbers
  13. static struct cdev hello_cdev;
  14. static struct class *hello_class; // Device class
  15. static char *buffers[NUM_MINORS]; // Buffers for each minor device
  16. static struct mutex buffer_locks[NUM_MINORS]; // Mutexes for buffer access
  17.  
  18. // File operations prototypes
  19. static int hello_open(struct inode *inode, struct file *file);
  20. static int hello_release(struct inode *inode, struct file *file);
  21. static ssize_t hello_read(struct file *file, char __user *user_buf, size_t count, loff_t *offset);
  22. static ssize_t hello_write(struct file *file, const char __user *user_buf, size_t count, loff_t *offset);
  23.  
  24. // File operations structure
  25. static const struct file_operations hello_fops = {
  26. .owner = THIS_MODULE,
  27. .open = hello_open,
  28. .release = hello_release,
  29. .read = hello_read,
  30. .write = hello_write,
  31. };
  32.  
  33. // Open operation
  34. static int hello_open(struct inode *inode, struct file *file) {
  35. int minor = iminor(inode); // Get minor number
  36. if (minor >= NUM_MINORS) {
  37. pr_err("hello_char_dev: Invalid minor number %d\n", minor);
  38. return -ENODEV;
  39. }
  40. file->private_data = (void *)(uintptr_t)minor; // Store minor number in private_data
  41. return 0;
  42. }
  43.  
  44. // Release operation
  45. static int hello_release(struct inode *inode, struct file *file) {
  46. return 0;
  47. }
  48.  
  49. // Read operation
  50. static ssize_t hello_read(struct file *file, char __user *user_buf, size_t count, loff_t *offset) {
  51. int minor = (uintptr_t)file->private_data;
  52. char *buffer = buffers[minor];
  53. size_t len = strlen(buffer);
  54.  
  55. if (*offset >= len)
  56. return 0; // EOF
  57.  
  58. if (count + *offset > len)
  59. count = len - *offset;
  60.  
  61. if (mutex_lock_interruptible(&buffer_locks[minor]))
  62. return -ERESTARTSYS;
  63.  
  64. if (copy_to_user(user_buf, buffer + *offset, count)) {
  65. mutex_unlock(&buffer_locks[minor]);
  66. return -EFAULT;
  67. }
  68.  
  69. *offset += count;
  70. mutex_unlock(&buffer_locks[minor]);
  71. return count;
  72. }
  73.  
  74. // Write operation
  75. static ssize_t hello_write(struct file *file, const char __user *user_buf, size_t count, loff_t *offset) {
  76. int minor = (uintptr_t)file->private_data;
  77. char *buffer = buffers[minor];
  78.  
  79. if (count >= BUFFER_SIZE)
  80. count = BUFFER_SIZE - 1;
  81.  
  82. if (mutex_lock_interruptible(&buffer_locks[minor]))
  83. return -ERESTARTSYS;
  84.  
  85. if (copy_from_user(buffer, user_buf, count)) {
  86. mutex_unlock(&buffer_locks[minor]);
  87. return -EFAULT;
  88. }
  89.  
  90. buffer[count] = '\0'; // Null-terminate the string
  91. mutex_unlock(&buffer_locks[minor]);
  92. return count;
  93. }
  94.  
  95. // Module initialization
  96. static int __init hello_init(void) {
  97. int ret, i;
  98.  
  99. // Allocate device numbers
  100. ret = alloc_chrdev_region(&dev_num, 0, NUM_MINORS, "hello_char_dev");
  101. if (ret < 0) {
  102. pr_err("hello_char_dev: Failed to allocate device numbers\n");
  103. return ret;
  104. }
  105.  
  106. // Create device class
  107. hello_class = class_create(THIS_MODULE, "hello_char_class");
  108. if (IS_ERR(hello_class)) {
  109. pr_err("hello_char_dev: Failed to create device class\n");
  110. ret = PTR_ERR(hello_class);
  111. goto unregister_region;
  112. }
  113.  
  114. // Initialize buffers and mutexes
  115. for (i = 0; i < NUM_MINORS; i++) {
  116. buffers[i] = kmalloc(BUFFER_SIZE, GFP_KERNEL);
  117. if (!buffers[i]) {
  118. pr_err("hello_char_dev: Failed to allocate memory for buffer %d\n", i);
  119. ret = -ENOMEM;
  120. goto cleanup_buffers;
  121. }
  122. strcpy(buffers[i], "empty"); // Initialize buffers with "empty"
  123. mutex_init(&buffer_locks[i]);
  124.  
  125. // Create device files
  126. if (!device_create(hello_class, NULL, MKDEV(MAJOR(dev_num), i), NULL, "hello_dev%d", i)) {
  127. pr_err("hello_char_dev: Failed to create device file for minor %d\n", i);
  128. ret = -ENOMEM;
  129. goto cleanup_buffers;
  130. }
  131. }
  132.  
  133. // Initialize cdev
  134. cdev_init(&hello_cdev, &hello_fops);
  135. hello_cdev.owner = THIS_MODULE;
  136.  
  137. ret = cdev_add(&hello_cdev, dev_num, NUM_MINORS);
  138. if (ret < 0) {
  139. pr_err("hello_char_dev: Failed to add cdev\n");
  140. goto cleanup_devices;
  141. }
  142.  
  143. pr_info("hello_char_dev: Registered with major number %d\n", MAJOR(dev_num));
  144. return 0;
  145.  
  146. cleanup_devices:
  147. for (i = 0; i < NUM_MINORS; i++)
  148. device_destroy(hello_class, MKDEV(MAJOR(dev_num), i));
  149.  
  150. cleanup_buffers:
  151. for (i = 0; i < NUM_MINORS; i++)
  152. kfree(buffers[i]);
  153.  
  154. class_destroy(hello_class);
  155.  
  156. unregister_region:
  157. unregister_chrdev_region(dev_num, NUM_MINORS);
  158. return ret;
  159. }
  160.  
  161. // Module cleanup
  162. static void __exit hello_exit(void) {
  163. int i;
  164.  
  165. cdev_del(&hello_cdev);
  166.  
  167. for (i = 0; i < NUM_MINORS; i++) {
  168. device_destroy(hello_class, MKDEV(MAJOR(dev_num), i));
  169. kfree(buffers[i]);
  170. }
  171.  
  172. class_destroy(hello_class);
  173. unregister_chrdev_region(dev_num, NUM_MINORS);
  174. pr_info("hello_char_dev: Unregistered\n");
  175. }
  176.  
  177. module_init(hello_init);
  178. module_exit(hello_exit);
  179.  
  180. MODULE_LICENSE("GPL");
  181. MODULE_AUTHOR("Improved by ChatGPT");
  182. MODULE_DESCRIPTION("Improved Character Device with Dynamic Major Number and Device Files");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement