Saturday, March 26, 2011

How to Pass Command Line Arguments to a Kernel Module

Generally the word command line arguments make you strike to argc/argv in C, here coming to Linux kernel modules approach is bit different and even easy to....!! lets go for a walk on this concept.

To allow arguments to be passed to your module, declare the variables that will take the values of the command line arguments as global and then use the module_param() macro, defined in linux/moduleparam.h to set the mechanism up.
Value is assigned to this variable at runtime by a command line arguments that are given like $ insmod mymodule.ko myvariable=5 while inserting/loading the module into kernel.

The variable declarations and macros should be placed at the beginning of the module for clarity.

In this post Loadable Kernel Module i have explained the basic concepts of kernel modules.

The module_param() macro takes 3 arguments: 
  • arg1 : The name of the variable.
  • arg2 : Its type
  • arg3 : Permissions for the corresponding file in sysfs. 
Example Code Snippet :

static int myint =51;
module_param(myint, int, 0);
MODULE_PARM_DESC(myint,"this is the int variable");

Integer types can be signed as usual or unsigned. 

MODULE_PARM_DESC() macro used for giving the description of variable.
Example for all the data types are given below:
static int dint;
module_param(dint, int, 0);
MODULE_PARM_DESC(dint,"this is the dynamic int variable");

static short myshort = 51;
module_param(myshort, short, 0);
MODULE_PARM_DESC(myshort,"this is the short variable");
static long int mylong = 45100;
module_param(mylong, long , 0);
MODULE_PARM_DESC(myshort,"this is the long int variable");

static char *mychar = "Smack Down";
module_param(mychar, charp, 0);
MODULE_PARM_DESC(myshort,"this is the characte string variable");

static int myarr[2] = {51,43};
static int arr_argc = 0;
module_param_array(myarr, int,&arr_argc, 0);
MODULE_PARM_DESC(myarr,"this is the array variable");

Example Code:

Code:
#include <linux/kernel.h> /*needed for priority messages in prink*/
#include <linux/init.h> /*needed for macros*/
#include <linux/module.h> /*needed for all modules*/

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vamshi Krishna Gajjela");
MODULE_DESCRIPTION("Test Module Parameters");

static short myshort = 51;
static int myint = 451;
static int dint;
static long int mylong = 45100;
static char *mychar = "Smack Down";
static int myarr[2] = {51,43};
static int arr_argc = 0;
static int hello_world2_data __initdata = 3;

module_param(dint, int, 0);
MODULE_PARM_DESC(dint,"this is the dynamic int variable");

module_param(myshort, short, 0);
MODULE_PARM_DESC(myshort,"this is the short variable");

module_param(myint, int, 0);
MODULE_PARM_DESC(myint,"this is the int variable");


module_param(mylong, long , 0);
MODULE_PARM_DESC(myshort,"this is the long int variable");


module_param(mychar, charp, 0);
MODULE_PARM_DESC(myshort,"this is the characte string variable");


module_param_array(myarr, int,&arr_argc, 0);
MODULE_PARM_DESC(myarr,"this is the array variable");

int __init hello_world2_init(void){
 int i;
 printk(KERN_INFO "Vamshi : Entered2 : data = %d",hello_world2_data);
 printk(KERN_INFO "Value of the the short variable is = %hd",myshort);
 printk(KERN_INFO "Value of the the short variable is = %d",myint);
 printk(KERN_INFO "Value of the the dint variable is = %d",dint);
 printk(KERN_INFO "Value of the the short variable is = %ld",mylong);
 printk(KERN_INFO "Value of the the short variable is = %s",mychar);
 for(i=0;i<sizeof(myarr)/sizeof(int);i++){
  printk(KERN_INFO "arr[%d] = %d\n",i,myarr[i]);
 }
 return 0;
}
void __exit hello_world2_exit(void){
 printk(KERN_INFO "Vamshi : Exited2 ");
}

module_init(hello_world2_init);
module_exit(hello_world2_exit);





Note: Copying the code directly into your source.c file will also copies the invisible characters and finally you will left out with stray errors, i recommend you to type the code and that even becomes a practice.

Makefile:
obj-m := hello_world2.o
all:
      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean


Building module Sequence Steps:



Click to Download Code

Use Cases of Module Parameters:
  • When there is a need to change the irq line of the module then its the best way to pass the irq number as command line argument using module parameter concept.
  • Base address of the register map of a module can be passed at module load time using insmod based on this command line arguments.


4 comments:

  1. Hi,

    It is really informative. Can you help me to understand- how does value in user space gets transferred to kernel space (code flow in kernel or function which does that)in this scenario ie> command line arguements (module_param() macro).

    Thanks,
    Harish

    ReplyDelete
  2. Hi Harish....!
    there are many was we can pass values from user space to kernel space, that depends....!
    one thing in the form of pages, by locking to make sure that its not use by other processes.

    the other by using zero copy...! this feature is available by applying patches the the kernel.

    or by passing the address of the buffer, by converting logical address to physical or vice verse......!

    if above approaches doesn't meet your requirement, tell we exactly where u r stuck...! i try to help you..!

    Hey any suggestions for my blog....! :-)

    ReplyDelete
  3. Great, its really helpful for me...

    ReplyDelete
  4. Thanks naveen ! I will work to add more information on device drivers, stay tuned.

    ReplyDelete