-1

I'm trying to understand some example code my lecturer gave me.

It is a method of transferring data from user space into kernel space via a /proc file. This is the only code he gave me and I feel like I'm missing the user space program and I don't think he's explained what's going on very well.

He's trying to demonstrate locking files via semaphores, and also transferring the data I believe. The things I'm struggling to understand are:

  • what is the "reference count" (He mentions it in the comments for procfs_open and procfs_close)
  • Why would he use a proc file? It appears to do nothing.
  • What do module_put and try_module_get do? I can't find any remotely good explanations online.
  • How would I trigger the kernelWrite function from userspace? So that I know how I can actually transfer the data, not just receive it.

Here is the code:

#define BUFFERLENGTH 256
#define INCREASE_COUNTER 'I'
#define SHOW_COUNTER 'S'

#define PROC_ENTRY_FILENAME "kernelWrite"

DECLARE_RWSEM(counter_sem); /* semaphore to protect counter access */

static struct proc_dir_entry *Our_Proc_File;

int counter1 = 0;
int counter2 = 0;

/* displays the kernel table - for simplicity via printk */
void show_table (void) {

    int tmp1;
    int tmp2;

    down_read (&counter_sem); /* lock for reading */
    tmp1 = counter1;
    tmp2 = counter2;
    up_read (&counter_sem); /* unlock reading */
    printk (KERN_INFO "kernelWrite:The counters are %d, %d\n", tmp1, tmp2);

}

void increase_counter (void) {

    down_write (&counter_sem); /* lock for writing */
    counter1++;
    counter2++;
    up_write (&counter_sem);

}

/* This function reads in data from the user into the kernel */
ssize_t kernelWrite (struct file *file, const char __user *buffer, size_t count, loff_t *offset) {


    char command;

    printk (KERN_INFO "kernelWrite entered\n");


    if (get_user (command, buffer)) {
    return -EFAULT;
    }

  switch (command) {
    case INCREASE_COUNTER:
    increase_counter ();
    break;
    case SHOW_COUNTER:
    show_table ();
      break;
    default: 
      printk (KERN_INFO "kernelWrite: Illegal command \n");
  }
  return count;
}



/* 
 * The file is opened - we don't really care about
 * that, but it does mean we need to increment the
 * module's reference count. 
 */
int procfs_open(struct inode *inode, struct file *file)
{
    printk (KERN_INFO "kernelWrite opened\n");
    try_module_get(THIS_MODULE);
    return 0;
}

/* 
 * The file is closed - again, interesting only because
 * of the reference count. 
 */
int procfs_close(struct inode *inode, struct file *file)
{
    printk (KERN_INFO "kernelWrite closed\n");
    module_put(THIS_MODULE);
    return 0;       /* success */
}

const struct file_operations File_Ops_4_Our_Proc_File = {
    .owner = THIS_MODULE,
    .write   = kernelWrite,
    .open    = procfs_open,
    .release = procfs_close,
};


int init_module(void)
{



    /* create the /proc file */
    Our_Proc_File = proc_create_data (PROC_ENTRY_FILENAME, 0644, NULL, &File_Ops_4_Our_Proc_File, NULL);

    /* check if the /proc file was created successfuly */
    if (Our_Proc_File == NULL){
    printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
           PROC_ENTRY_FILENAME);
    return -ENOMEM;
    }

    printk(KERN_INFO "/proc/%s created\n", PROC_ENTRY_FILENAME);

    return 0;   /* success */

}

void cleanup_module(void)
{

  remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
  printk(KERN_INFO "/proc/%s removed\n", PROC_ENTRY_FILENAME);  

  printk(KERN_INFO "kernelWrite:Proc module unloaded.\n");

}  
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
toastedDeli
  • 570
  • 5
  • 28
  • 1
    Several questions, each of them is easily googled. E.g. the first one: https://www.kernel.org/doc/htmldocs/kernel-hacking/routines-module-use-counters.html. (The link also contains an explanation, why given code **don't need** to use the module's reference counter.) – Tsyvarev Dec 04 '17 at 17:36

1 Answers1

2

Several questions, several answers:

1 Module reference count and try_module_get and module_put: Each kernel module has usage count, in particular if it is referenced by any other module or used any other way. In this case, when doing opening file it will prevent module from being removed, and after closing the file, it will remove reference. Why it should not be used is explained here

2 Proc file: Uses File_Ops_4_Our_Proc_File structure. You need to perform action in user space to trigger appropriate action on proc file (namely open, close and write).

3 Triggering actions. For example (from bash):

echo 'I' > /proc/kernelWrite

Which writes character 'I' to proc file, triggering File_Ops_4_Our_Proc_File.write, effectively calling kernelWrite.

nowaqq
  • 261
  • 3
  • 10