Advertisement
hieudoan

solidusmodule.c

Sep 23rd, 2018
377
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.83 KB | None | 0 0
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>  //file_operations structure- which of course allows use to open/close, read/write to device
  4. #include <linux/cdev.h> //char device; make cdev available
  5. #include <linux/semaphore.h> //used to access semaphore: synchronization behaviors
  6. #include <asm/uaccess.h> //copy_to_user; copy_from_user
  7. #include <linux/uaccess.h>
  8. #include <linux/random.h>
  9.  
  10. //(1) Create a structure for our fake device
  11. struct fake_device{
  12.     char data[100];
  13.     struct semaphore sem;
  14. }virtual_device;
  15.  
  16. //(2) To later register our device we need a cdev object and some other variables
  17.  
  18. struct cdev *mcdev;  //m stands 'my'
  19. int major_number;  //will store our major number-extracted from dev_t using marco - mknod /directory/file c major minor
  20. int ret;           //will be used to hold return values of functions; this is because the kernel stack is very small
  21.  
  22. dev_t dev_num;
  23.  
  24. #define DEVICE_NAME  "solidusdevice"
  25.  
  26. //(7)called on device_file open
  27. //      inode reference to the file on disk
  28. //      and contains information about that file
  29. //      struct file is represents an abstract open file
  30. int device_open(struct inode* inode, struct file *filp){
  31.     //only allow one process to open this device by using a semaphore as mutual exclusive lock-mutex
  32.     if(down_interruptible(&virtual_device.sem)!=0){
  33.         printk(KERN_ALERT "soliduscode: could not lock device during open");
  34.         return -1;
  35.     }
  36.     printk(KERN_INFO "soliduscode: opened device");
  37.     return 0;
  38. }
  39. //(8) called when user wants to get information from the device
  40. ssize_t device_read(struct file* filp, char* bufStoreData,size_t bufCount,loff_t* curOffset){
  41.     //take data from kernel space (device) to user space (process)
  42.     //copy_to_user (destination,source,sizeToTransfer)
  43.     // printk(KERN_INFO "soliduscode: Reading from device");
  44.     // ret = copy_to_user(bufStoreData,virtual_device.data,bufCount);
  45.     // return ret;
  46.     int randomNumber;
  47.     get_random_bytes(&randomNumber,sizeof(randomNumber));
  48.     // printk(KERN_ALERT "TEST: %d",randomNumber);
  49.     return randomNumber;
  50.     // return 999;
  51. }
  52.  
  53. //(9) called when user wants to send information to the device
  54. ssize_t device_write(struct file* filp,const char* bufSourceData,size_t bufCount,loff_t* curOffset){
  55.     //send data from user to kernel
  56.     //copy_from_user (dest, source,count);
  57.     printk(KERN_INFO "soliduscode: writing to device");
  58.     ret = copy_from_user(virtual_device.data,bufSourceData, bufCount);
  59.     return ret;
  60. }
  61.  
  62. //(10) called upon user close
  63. int device_close(struct inode *inode, struct file *filp){
  64.     //by calling up, which is opposite of down for semaphore, we release the mutex that we obtained at device open
  65.     //this has the effect of allowing other process to use the device now
  66.     up(&virtual_device.sem);
  67.     printk(KERN_INFO "soliduscode: closed device");
  68.     return 0;
  69. }
  70.  
  71. //HERE
  72. //(6) Tell the kernel which functions to call when user operates on our device file
  73. struct file_operations fops={
  74.     .owner = THIS_MODULE,   //prevent unloadind of this module when operations are in use
  75.     .open = device_open,    //points to the method to call when opening the device
  76.     .release = device_close,  //points to the method to call when closing the device
  77.     .write = device_write,    //points to the method to call when writing to the device
  78.     .read = device_read     //points to the method to call when reading from the device
  79. };
  80.  
  81.  
  82.  //(3) Register your device with system: 2 step
  83. static int driver_entry(void){
  84.     //step (1) use dynamic allocation to assign our device
  85.     // a major number-- alloc_chrdev_region(dev_t*, unit fminor,unit count, char* name)
  86.     ret = alloc_chrdev_region(&dev_num,0,1,DEVICE_NAME);
  87.     if (ret<0) {
  88.         printk(KERN_ALERT "soliduscode: failed to allcate a major number");
  89.         return ret;
  90.     }
  91.     major_number= MAJOR(dev_num); //extracts the major number and store in our variable (MACRO)
  92.     printk(KERN_INFO "sokiduscode: major number is %d",major_number);
  93.     printk(KERN_INFO "\tuse \"mknod /dev/%s c %d 0\" for device file",DEVICE_NAME,major_number); //dmesg
  94.     //step(2)
  95.     mcdev=cdev_alloc(); //create our cdev structure, initialized our cdev
  96.     mcdev->ops=&fops; //struct file_operations
  97.     mcdev->owner=THIS_MODULE;
  98.     //now that we create cdev, we have to add it to the kernel
  99.     //int cdev_add(struct cdev* dev, dev_t num, unsigned int count);
  100.     ret = cdev_add(mcdev,dev_num,1);
  101.     if(ret<0) { //always check errors
  102.         printk(KERN_ALERT "soliduscode: unable to add cdev to kernel");
  103.         return ret;
  104.     }
  105.     //(4) Initialize our semaphore
  106.     sema_init(&virtual_device.sem,1);  //initial value of one
  107.  
  108.     return 0;
  109. }
  110.  
  111. static void driver_exit(void){
  112.     //(5) unregister everything in reverse order
  113.     //(a)
  114.     cdev_del(mcdev);
  115.     //(b)
  116.     unregister_chrdev_region(dev_num,1);
  117.     printk(KERN_ALERT "soliduscode: unloaded module");
  118. }
  119. //inform the kernel where to start and stop with our module/driver
  120. module_init(driver_entry);
  121. module_exit(driver_exit);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement