Advertisement
Adamova

mutexes

Apr 30th, 2016
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.94 KB | None | 0 0
  1. /*
  2. ** This "device" reverses strings that are written to it
  3. */
  4. #include <linux/module.h>
  5. #include <linux/init.h>
  6. #include <linux/kernel.h>
  7. #include <linux/cdev.h>
  8. #include <linux/mutex.h> //for mutexes
  9. #include <linux/types.h> // for dev_t typedef
  10. #include <linux/kdev_t.h> // for format_dev_t
  11. #include <linux/fs.h> // for alloc_chrdev_region()
  12.  
  13. #include <asm/uaccess.h> // for copy_to_user, copy_from_user
  14.  
  15. #define BUFSZ 6
  16.  
  17. static dev_t mydev; // (major,minor) value
  18. static struct cdev my_cdev;
  19. static struct mutex write;
  20. static struct mutex read;
  21. static struct semaphore bufempty;
  22. static struct semaphore buffull;
  23. static int access_count = 0;
  24. static char internal_buffer[BUFSZ];
  25.  
  26. /*********************************************************************
  27. ** The set of file operations that are implemented in this driver
  28. **********************************************************************/
  29. static ssize_t device_read(struct file *filp, char __user *buf,
  30. size_t len, loff_t *f_pos);
  31. static ssize_t device_write(struct file *filp, const char __user *buf,
  32. size_t len, loff_t *f_pos);
  33.  
  34. static int device_open( struct inode *, struct file *);
  35. static int device_close( struct inode *, struct file *);
  36.  
  37. static struct file_operations my_fops = {
  38. .owner = THIS_MODULE,
  39. .open = device_open,
  40. .read = device_read,
  41. .write = device_write,
  42. .release = device_close
  43. };
  44.  
  45.  
  46. /*********************************************************************
  47. ** Called when the device is opened (system call open)
  48. **********************************************************************/
  49. static int device_open(struct inode *inodep, struct file *filep)
  50. {
  51. //mutex_lock_interruptible(&reject); //rejecting mutex read
  52. access_count++;
  53. printk(KERN_ALERT "Reverse device opened %d time(s)\n", access_count);
  54.  
  55. if ( filep->f_mode & FMODE_READ )
  56. printk(KERN_ALERT "Reverse device opened for read\n" );
  57. if ( filep->f_mode & FMODE_WRITE )
  58. printk(KERN_ALERT "Reverse device opened for write\n" );
  59.  
  60. return 0;
  61. }
  62.  
  63.  
  64. /**********************************************************************
  65. ** Called when the device is read from
  66. **********************************************************************/
  67. static ssize_t device_read( struct file *filp, char __user *buf,
  68. size_t len, loff_t *f_pos )
  69. {
  70. // print some information
  71. mutex_lock_interruptible(&read);
  72. printk( KERN_INFO "In reverse read routine.\n" );
  73. printk( KERN_INFO "Length field is %lu.\n", (long unsigned int) len );
  74. printk( KERN_INFO "Offset is %lu.\n", (long unsigned int) *f_pos );
  75.  
  76. if ( internal_buffer[*f_pos] == '\0' )
  77. {
  78. printk( KERN_INFO "End of string, returning zero.\n" );
  79. return 0;
  80. }
  81.  
  82. if ( copy_to_user( buf, &internal_buffer[*f_pos], 1 ) != 0 )
  83. return -EFAULT;
  84.  
  85. *f_pos += 1;
  86. mutex_unlock(&read);
  87. mutex_unlock(&write);
  88. return 1; // return a single character
  89.  
  90. }
  91.  
  92.  
  93. /**********************************************************************
  94. ** Called when the device is written to
  95. **********************************************************************/
  96. static ssize_t device_write( struct file *filep, const char *buf,
  97. size_t len, loff_t *f_pos )
  98. {
  99. mutex_lock_interruptible(&write); //rejecting mutex write
  100. int i;
  101. int count = 0;
  102. i = 0; // start at the end to reverse
  103.  
  104. // print some information
  105. printk( KERN_INFO "In reverse write routine.\n" );
  106. printk( KERN_INFO "Length field is %lu.\n", (long unsigned int) len );
  107. printk( KERN_INFO "Offset is %lu.\n", (long unsigned int) *f_pos );
  108.  
  109. // clear the buffer
  110. memset( internal_buffer, 0, BUFSZ );
  111. *f_pos = 0;
  112.  
  113. if(len>BUFSZ){ //checking if the input is bigger than the size of buffer
  114. int k=0;
  115. for(k=0; k<BUFSZ-1; k++){ //only BUFSZ-1
  116. if ( copy_from_user( &internal_buffer[count++], buf+i, 1 ) != 0 )
  117. return -EFAULT;
  118. i++;
  119. len--;
  120. }
  121. printk( KERN_INFO "FULL DEVICE.\n" );
  122. mutex_lock_interruptible(&write);
  123. //mutex_unlock(&read);
  124. }
  125. else{
  126. // copy the data from the user into the internal buffer
  127. while ( len > 0 )
  128. {
  129. if ( copy_from_user( &internal_buffer[count++], buf+i, 1 ) != 0 )
  130. return -EFAULT;
  131. i++;
  132. len--;
  133. }
  134. printk( KERN_INFO "DEVICE is not full.\n" );
  135. }
  136. mutex_unlock(&write);
  137. mutex_unlock(&read);
  138.  
  139. return count;
  140. }
  141.  
  142. /**********************************************************************
  143. ** Called when the device is closed
  144. **********************************************************************/
  145. static int device_close(struct inode *inodep, struct file *filep)
  146. {
  147. //mutex_unlock(&reject);
  148.  
  149.  
  150. printk(KERN_ALERT "reverse device closed !\n");
  151. //rejecting mutex unlock
  152. return 0;
  153. }
  154.  
  155.  
  156. /**********************************************************************
  157. ** Called when this driver module is loaded
  158. **********************************************************************/
  159. static int __init chardrv_in(void)
  160. {
  161. int result;
  162. printk(KERN_INFO "module reverse driver being loaded.\n");
  163. mutex_init(&write);
  164. mutex_init(&read);
  165. sema_init(&bufempty, BUFSZ);
  166. sema_init(&buffull, BUFSZ);
  167. result = alloc_chrdev_region(&mydev, 0, 1, "rday");
  168. if ( result < 0 )
  169. {
  170. printk(KERN_WARNING "Failed to allocate major/minor numbers");
  171. return result;
  172. }
  173.  
  174. cdev_init(&my_cdev, &my_fops);
  175. my_cdev.owner = THIS_MODULE;
  176. result = cdev_add(&my_cdev, mydev, 1);
  177. if ( result < 0 )
  178. {
  179. printk(KERN_WARNING "Failed to register the cdev structure");
  180. return result;
  181. }
  182.  
  183. return 0;
  184. }
  185.  
  186.  
  187. /*********************************************************************
  188. ** Called when this driver module is unloaded
  189. *********************************************************************/
  190. static void __exit chardrv_out(void)
  191. {
  192. printk(KERN_INFO "module chardrv being unloaded.\n");
  193.  
  194. cdev_del(&my_cdev);
  195. unregister_chrdev_region(mydev, 1);
  196.  
  197. }
  198.  
  199. module_init(chardrv_in);
  200. module_exit(chardrv_out);
  201.  
  202. MODULE_AUTHOR("Robert P. J. Day, http://crashcourse.ca");
  203. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement